• 修改MP3属性


    by 蝈蝈俊.net

    Categories: 未分类

    Tags: .net 3.0, .net 3.5, .Net 4.0, .net 编程心得, 技术随笔

    Comments: 1 Comment

    Published on: 2009 年 12 月 02 日

    最近在处理一批下载的评书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文件属性
            //// <summary>
            /// 标题
            /// </summary>
            [MediaProperty("Title")]
            public string Title { get; set; }
    
            /// <summary>
            /// 子标题
            /// </summary>
            [MediaProperty("Media.SubTitle")]
            public string SubTitle { get; set; }
    
            /// <summary>
            /// 星级
            /// </summary>
            [MediaProperty("Rating")]
            public uint? Rating { get; set; }
    
            /// <summary>
            /// 备注
            /// </summary>
            [MediaProperty("Comment")]
            public string Comment { get; set; }
    
            /// <summary>
            /// 艺术家
            /// </summary>
            [MediaProperty("Author")]
            public string Author { get; set; }
    
            /// <summary>
            /// 唱片集
            /// </summary>
            [MediaProperty("Music.AlbumTitle")]
            public string AlbumTitle { get; set; }
    
            /// <summary>
            /// 唱片集艺术家
            /// </summary>
            [MediaProperty("Music.AlbumArtist")]
            public string AlbumArtist { get; set; }
    
            /// <summary>
            /// 年
            /// </summary>
            [MediaProperty("Media.Year")]
            public uint? Year { get; set; }
    
            /// <summary>
            /// 流派
            /// </summary>
            [MediaProperty("Music.Genre")]
            public string Genre { get; set; }
    
            /// <summary>
            /// #
            /// </summary>
            [MediaProperty("Music.TrackNumber")]
            public uint? TrackNumber { get; set; }
    
            /// <summary>
            /// 播放时间
            /// </summary>
            [MediaProperty("Media.Duration")]
            public string Duration { get; private set; }
    
            /// <summary>
            /// 比特率
            /// </summary>
            [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<DateTime?>).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

  • 相关阅读:
    POJ 3685 Matrix (二分套二分)
    mybatis-plus
    mysql 5.7 压缩包安装教程
    mysql备份
    mysql外键策略
    springboot使用RestTemplate以post方式发送json字符串参数(以向钉钉机器人发送消息为例)
    查询优化
    Spring Boot 创建定时任务(配合数据库动态执行)
    解决springboot序列化 json数据到前端中文乱码问题
    Mybatis 批量插入
  • 原文地址:https://www.cnblogs.com/anakin/p/2224192.html
Copyright © 2020-2023  润新知