用C#修改Mp3文件属性

 

最近在处理一批下载的评书mp3文件时,需要把它们的一些属性做修改为有规律的样式,以便自己播放时知道是播放的那首。

要修改的属性如下:

image

修改的方法我是使用的 http://www.cnblogs.com/TianFang/archive/2009/09/27/1574722.html  介绍的 使用 WindowsAPICodePack 的方法来修改。

但是上述地址给出的函数有个小bug,且具体如何用代码实现也没有说明,所以整理了这篇博客,

WindowsAPICodePack 在下面地址可以下载:

http://code.msdn.microsoft.com/WindowsAPICodePack

我下载的是 Windows API Code Pack 1.0.1  中的

WindowsAPICodePack.zip 
source code, 6927K, uploaded Nov 19

这个是源文件, 下载后打开可以看到 WindowsAPICodePack.sln 文件, 用 Visual Studio 编译后,我们可以得到下面2个文件:

Microsoft.WindowsAPICodePack.dll

Microsoft.WindowsAPICodePack.Shell.dll

这就是我们项目中要引用的两个文件。

引用这两个文件后,再在项目中增加一个文件,内容如下(注意把namespace修改为你自己的):

这个文件中也就是我说的http://www.cnblogs.com/TianFang/archive/2009/09/27/1574722.html  介绍的有小bug的文件,有错误的部分看下面我的注释。文件内容如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.WindowsAPICodePack.Shell;

using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

using System.Reflection;



namespace _52PS_WpfApplication

{

    public class MediaTags

    {

        #region Mp3文件属性

        //// 

        /// 标题

        /// 

        [MediaProperty("Title")]

        public string Title { get; set; }



        /// 

        /// 子标题

        /// 

        [MediaProperty("Media.SubTitle")]

        public string SubTitle { get; set; }



        /// 

        /// 星级

        /// 

        [MediaProperty("Rating")]

        public uint? Rating { get; set; }



        /// 

        /// 备注

        /// 

        [MediaProperty("Comment")]

        public string Comment { get; set; }



        /// 

        /// 艺术家

        /// 

        [MediaProperty("Author")]

        public string Author { get; set; }



        /// 

        /// 唱片集

        /// 

        [MediaProperty("Music.AlbumTitle")]

        public string AlbumTitle { get; set; }



        /// 

        /// 唱片集艺术家

        /// 

        [MediaProperty("Music.AlbumArtist")]

        public string AlbumArtist { get; set; }



        /// 

        /// 年

        /// 

        [MediaProperty("Media.Year")]

        public uint? Year { get; set; }



        /// 

        /// 流派

        /// 

        [MediaProperty("Music.Genre")]

        public string Genre { get; set; }



        /// 

        /// #

        /// 

        [MediaProperty("Music.TrackNumber")]

        public uint? TrackNumber { get; set; }



        /// 

        /// 播放时间

        /// 

        [MediaProperty("Media.Duration")]

        public string Duration { get; private set; }



        /// 

        /// 比特率

        /// 

        [MediaProperty("Audio.EncodingBitrate")]

        public string BitRate { get; private set; }

        #endregion



        public MediaTags(string mediaPath)

        {

            //var obj = ShellObject.FromParsingName(mp3Path);   //缩略图,只读

            //obj.Thumbnail.Bitmap.Save(@"R:\2.jpg");



            Init(mediaPath);

        }



        void Init(string mediaPath)

        {

            using (var obj = ShellObject.FromParsingName(mediaPath))

            {

                var mediaInfo = obj.Properties;

                foreach (var properItem in this.GetType().GetProperties())

                {

                    var mp3Att = properItem.GetCustomAttributes(typeof(MediaPropertyAttribute), false).FirstOrDefault();

                    var shellProper = mediaInfo.GetProperty("System." + mp3Att);

                    var value = shellProper == null ? null : shellProper.ValueAsObject;



                    if (value == null)

                    {

                        continue;

                    }



                    if (shellProper.ValueType == typeof(string[]))    //艺术家,流派等多值属性

                    {

                        properItem.SetValue(this, string.Join(";", value as string[]), null);

                    }

                    else if (properItem.PropertyType != shellProper.ValueType)    //一些只读属性,类型不是string,但作为string输出,避免转换 如播放时间,比特率等

                    {

                        properItem.SetValue(this, value == null ? "" : shellProper.FormatForDisplay(PropertyDescriptionFormat.Default), null);

                    }

                    else

                    {

                        properItem.SetValue(this, value, null);

                    }

                }

            }

        }



        public void Commit(string mp3Path)

        {

            var old = new MediaTags(mp3Path);



            using (var obj = ShellObject.FromParsingName(mp3Path))

            {

                var mediaInfo = obj.Properties;

                foreach (var proper in this.GetType().GetProperties())

                {

                    var oldValue = proper.GetValue(old, null);

                    var newValue = proper.GetValue(this, null);



                    if (oldValue == null && newValue == null)

                    {

                        continue;

                    }



                    // 这里做了修改  郭红俊 20091202

                       // 原先在旧值存在,新值没有给出时,会有空对象引用的bug

                    //if (oldValue == null || !oldValue.Equals(newValue))



                    // 新的逻辑 新值存在时, 则替换旧值

                    if ((newValue != null) && (newValue.ToString().Trim().Length > 0) && (newValue != oldValue))

                    {

                        var mp3Att = proper.GetCustomAttributes(typeof(MediaPropertyAttribute), false).FirstOrDefault();

                        var shellProper = mediaInfo.GetProperty("System." + mp3Att);

                        Console.WriteLine(mp3Att);



                        if (newValue == null) newValue = string.Empty;



                        SetPropertyValue(shellProper, newValue);

                    }

                }

            }

        }



        #region SetPropertyValue

        static void SetPropertyValue(IShellProperty prop, object value)

        {

            if (prop.ValueType == typeof(string[]))        //只读属性不会改变,故与实际类型不符的只有string[]这一种

            {

                string[] values = (value as string).Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                (prop as ShellProperty<string[]>).Value = values;

            }

            if (prop.ValueType == typeof(string))

            {

                (prop as ShellProperty<string>).Value = value as string;

            }

            else if (prop.ValueType == typeof(ushort?))

            {

                (prop as ShellProperty<ushort?>).Value = value as ushort?;

            }

            else if (prop.ValueType == typeof(short?))

            {

                (prop as ShellProperty<short?>).Value = value as short?;

            }

            else if (prop.ValueType == typeof(uint?))

            {

                (prop as ShellProperty<uint?>).Value = value as uint?;

            }

            else if (prop.ValueType == typeof(int?))

            {

                (prop as ShellProperty<int?>).Value = value as int?;

            }

            else if (prop.ValueType == typeof(ulong?))

            {

                (prop as ShellProperty<ulong?>).Value = value as ulong?;

            }

            else if (prop.ValueType == typeof(long?))

            {

                (prop as ShellProperty<long?>).Value = value as long?;

            }

            else if (prop.ValueType == typeof(DateTime?))

            {

                (prop as ShellProperty).Value = value as DateTime?;

            }

            else if (prop.ValueType == typeof(double?))

            {

                (prop as ShellProperty<double?>).Value = value as double?;

            }

        }

        #endregion



        #region MediaPropertyAttribute

        [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]

        sealed class MediaPropertyAttribute : Attribute

        {

            public string PropertyKey { get; private set; }

            public MediaPropertyAttribute(string propertyKey)

            {

                this.PropertyKey = propertyKey;

            }



            public override string ToString()

            {

                return PropertyKey;

            }

        }

        #endregion

    }



}

 

使用这个文件的一个简单范例如下:

这个范例修改程序运行时目录下指定规范名字mp3文件的标题属性,当然其他属性也是类似的。

        private void btn_2_Click(object sender, RoutedEventArgs e)

        {

            MediaTags mt = new MediaTags(Environment.CurrentDirectory);



            for (int i = 1; i <= 16; i++)

            {

                string fileName = string.Format("{0}\\童林传_{1:000}.mp3", Environment.CurrentDirectory, i);

                mt.Title = string.Format("童林传 {0:000}",i);

                mt.Author = "单田芳";

                mt.Commit(fileName);

            }



        }

 

参考资料:

用C#修改Mp3文件属性 
http://www.cnblogs.com/TianFang/archive/2009/09/27/1574722.html

你可能感兴趣的:(C#)