• 利用 Windows API Code Pack 修改音乐的 ID3 信息


    朋友由于抠门 SD 卡买小了,结果音乐太多放不下,又不舍得再买新卡,不得已决定重新转码,把音乐码率压低一点,牺牲点音质来换空间(用某些人的话说,反正不是搞音乐的,听不出差别)…

    结果千千静听(百度音乐)转码后会把音乐 ID3 信息里的标题当文件名…(PS:怀念当年的 千千静听…)

    结果成了这个模样:

    image  image

    由于数量较多,收工改会死人的..

    所以只好想办法用程序来批量改

    找到了园友的老文章:http://www.cnblogs.com/TianFang/archive/2009/09/27/1574722.html

    于是决定用 Windows API Code Pack

    不过 MS 网站已经木有 Windows API Code Pack 的链接了

    不过找起来也不麻烦

    找到后新建工程,添加引用这两个 dll 就可以了

    image

    然后在工程里新建类 MediaTags,写入内容如下 :

        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(PropertyDescriptionFormatOptions.None), 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;
                        }
     
                        if (oldValue == null || !oldValue.Equals(newValue))
                        {
                            var mp3Att = proper.GetCustomAttributes(typeof(MediaPropertyAttribute), false).FirstOrDefault();
                            var shellProper = mediaInfo.GetProperty("System." + mp3Att);
                            Console.WriteLine(mp3Att);
                            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,批量替换标题

            static void Main(string[] args)
            {
                string fileDirectory = System.IO.Directory.GetCurrentDirectory();
                DirectoryInfo folder = new DirectoryInfo(fileDirectory);
    
                foreach (FileInfo file in folder.GetFiles("*.mp3"))
                {
                    MediaTags mt = new MediaTags(file.FullName);
                    mt.Title = file.FullName.Replace(fileDirectory + "\", "").Replace(".mp3", "");
                    mt.Commit(file.FullName);
                }
            }

    完成效果,剩下批量转换就可以了

    image

  • 相关阅读:
    为什么要设计好目录结构?
    python 程序退出方式
    mysql超出最大连接数解决方法
    服务器网络连接状态
    Python判断文件是否存在的三种方法【转】
    Nginx日志中的金矿 -- 好文收藏
    vsphere中的linux虚拟机安装vmware-tools
    vsphere中的vcenter创建esxi模板虚拟机新建无法连接网络
    linux同步系统时间
    Linux内核中TCP SACK机制远程DoS预警通告
  • 原文地址:https://www.cnblogs.com/sun8134/p/3838654.html
Copyright © 2020-2023  润新知