开源的.NET媒体文件操作组件TagLib#解析

 

人生得意须尽欢 莫使金樽空对月。写博客都会在吃饭后,每次吃饭都要喝上二两小酒,写博客前都要闲扯,这些都是个人爱好,改不掉了,看不惯的人,还望多多包含一下,有相同爱好的同学,咱们可以一起喝着小酒一边吹牛逼。总有人跟我说要做正事,但是这个世界什么叫做正事什么叫做闲事呢?见解各不相同吧,我自己喜欢的在我的世界就是正事。

万事急不得,需要等待时机和足够的积累方可一举成事。

接着前面的组件进行一个简单的介绍,在写博文之前,自己都会做一个简单的了解和应用,毕竟利人必须先利己嘛。有时候没有必要去写一些简单的demo,拿出来会占用篇幅,在实际的项目中使用起来也不会是那么顺畅,只需要了解其原理和使用场景,在项目中都应该可以很好的应用,真正好的代码是需要经过实际的业务需求打磨和从实际的业务去修改和提炼。所以在这些博文中,会简单的介绍背景、应用方法,以及组件的核心对象。真正深入的了解,需要自己去学习。

知识就是如此,站在前人的肩膀上去展望。有人发现了0和1,所以我们如今不需要再去设计阴和阳做替代。那些所谓的项目中的干货,我只能说,项目千千万,每一个都有不同的需求和场景,如果要想都学完,那只是一些人拿来装逼的笑话,只要把握核心原理,结合真实业务,以自己的思维去整合,得到的就是最合适的技术和框架。

前面扯淡半天,下面就直接进入正题。(如果有人有意见,我觉得没有什么不是一瓶酒解决不掉了,对我有意见,可以约出来干一架,也可以喝一顿,我请...哈哈哈...)

一.TagLib#组件概述

TagLib#用于处理媒体文件,例如视频,音频和照片等等,TagLib#采用LGPL和MPL两种开源协议。TagLib#是用于读取和编辑几种流行音频格式的元数据的库。目前,它支持 MP3文件的ID3v1和ID3v2,FLAC,MPC,Speex,WavPack,TrueAudio,WAV,AIFF,MP4和ASF文件中的Ogg Vorbis注释和ID3标签和Vorbis注释。

该组件属于比较老的一种了,在GitHub上一直都在更新修改。该库由2001年开始创建,但是该库一直有人在维护,需要使用到相关功能的同学,可以看看该组件。该组件的当前版本为2.1 。该库的地址:https://github.com/mono/taglib-sharp。

TagLib#(又名taglib-sharp)是一个用于阅读和写作的库媒体文件中的元数据,包括视频,音频和照片格式。

这个玩意的文档真是少,国内国外翻遍了,也没找到多少,写一篇不容易啊。

在这里提供一个该库的扩展:https://github.com/timheuer/taglib-sharp-portable,该扩展库支持.NET Framework 4.5+,Windows 8+,Windows Phone 8.1,Windows Phone Silverlight 8,Xamarin.Android,Xamarin.iOS。

二.TagLib#组件应用

上面介绍了组件的背景和简单的叙述,下面就该介绍一下简单的应用,毕竟无法应用的组件,没有介绍的意义。这里如果需要编写较为通用的组件代码,可以自己根据项目需求进行总结,欢迎大家将自己的知识进行分享,分享自己的知识积累。

   1.解析照片

  public static TagLib.File ParsePhoto(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException(path);
}
TagLib.File file;
try
{
file = TagLib.File.Create(path);
}
catch (UnsupportedFormatException uex)
{
throw uex;
}
var image = file as TagLib.Image.File;
if (file == null)
{
throw new ArgumentNullException("file");
}
return image;
}

2.从文件中加载图片

public static void Main(string [] args)
{
if(args.Length < 2) {
Console.Error.WriteLine("USAGE: mono SetPictures.exe AUDIO_PATH IMAGE_PATH_1[...IMAGE_PATH_N]");
return;
}
TagLib.File file = TagLib.File.Create(args[0]);
Console.WriteLine("Current picture count: " + file.Tag.Pictures.Length);
Picture [] pictures = new Picture[args.Length - 1];
for(int i = 1; i < args.Length; i++) {
Picture picture = new Picture(args[i]);
pictures[i - 1] = picture;
}
file.Tag.Pictures = pictures;
file.Save();
Console.WriteLine("New picture count: " + file.Tag.Pictures.Length);
}

 3.加载音频文件

var tagFile = TagLib.File.Create("ironlionzion.mp3");
var tags = tagFile.GetTag(TagTypes.Id3v2);
string album = tags.Album;
string genre = "Hip-Hop, Rock";
var matchingFiles = Directory.GetFiles(@"Folder\SubFolder", "*.mp3",
SearchOption.AllDirectories).Where(x => { var f = TagLib.File.Create(x);
return ((TagLib.Id3v2.Tag) f.GetTag(TagTypes.Id3v2)).JoinedGenres == genre; });
foreach (string f in matchingFiles)
{
System.IO.File.Move(f, Path.Combine(@"D:\NewFolder", new FileInfo(f).Name));
}

 4.执行Tag

 public byte[] ExecuteTagging(byte[] inputFile, string title, string artist,
string album, string comment, uint year, string copyright, byte[] image)
{
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
writer.Write(inputFile);
using (var audioFile = TagLib.File.Create(new SimpleFileAbstraction(stream)))
{
audioFile.Tag.Title = title;
audioFile.Tag.Performers = new[] { artist };
audioFile.Tag.Album = album;
audioFile.Tag.Comment = comment;
audioFile.Tag.Genres = new[] { "Podcast" };
audioFile.Tag.Year = year;
audioFile.Tag.Copyright = copyright;
audioFile.Tag.Pictures = new[] { new Picture(image) };
audioFile.Save();
} stream.Position = 0;
using (var reader = new BinaryReader(stream))
{
return reader.ReadBytes((int)stream.Length);
}
}

三.TagLib#组件核心对象解析

介绍完基本的用法,如果需要了解更多,可以取GitHub自行下载查看源码,有比较详细的介绍,这里就不再做赘述,下面介绍一个该组件的一些核心对象。

1.File.Create()

 public static File Create (IFileAbstraction abstraction,string mimetype,ReadStyle propertiesStyle)
{
if(mimetype == null) {
string ext = String.Empty;
int index = abstraction.Name.LastIndexOf (".") + 1;
if(index >= 1 && index < abstraction.Name.Length)
ext = abstraction.Name.Substring (index,abstraction.Name.Length - index);
mimetype = "taglib/" + ext.ToLower(CultureInfo.InvariantCulture);
}
foreach (FileTypeResolver resolver in file_type_resolvers) {
File file = resolver(abstraction, mimetype,propertiesStyle);
if(file != null)return file;
}
if (!FileTypes.AvailableTypes.ContainsKey(mimetype))
throw new UnsupportedFormatException (
String.Format (CultureInfo.InvariantCulture,"{0} ({1})",abstraction.Name,mimetype));
Type file_type = FileTypes.AvailableTypes[mimetype];
try {
File file = (File) Activator.CreateInstance(file_type,new object [] {abstraction, propertiesStyle});
file.MimeType = mimetype;
return file;
} catch (System.Reflection.TargetInvocationException e) {
PrepareExceptionForRethrow(e.InnerException);
throw e.InnerException;
}
}

该方法用于创建一个File子类的新实例对于指定的文件抽象,mime类型和读取风格。该方法存在6个重载,接受两个参数,abstraction一个IFileAbstraction对象要使用的时候从当前实例读取和写入。mimetype包含mime类型的string对象在选择要使用的适当类时使用,或langword =null如果扩展名name abstraction被使用。propertiesStyle一个ReadStyle值指定的级别从...阅读媒体信息时使用的细节新实例。该方法返回一个File对象,一个新的实例File从中读取指定抽象。Activator.CreateInstance()指定参数匹配程度最高的构造函数创建指定类型的实例。

2.File.WriteBlock()

 public void WriteBlock (ByteVector data)
{
if (data == null)
throw new ArgumentNullException ("data");
Mode = AccessMode.Write;
file_stream.Write (data.Data, 0, data.Count);
}

该方法将一个数据块写入该代表的文件当前实例在当前查找位置,参数data一个ByteVector包含数据的对象写入当前实例。AccessMode是一个枚举类型,指定当前文件访问操作的类型允许在File的实例上。file_stream.Write (data.Data, 0, data.Count)向当前流中写入字节序列,并将此流中的当前位置提升写入的字节数。

四.总结

技术没有最好,只有最合适。不是你项目应用了当前最先进的技术,就说你的项目就是最先进的,只有你项目使用了最合适的技术,才可以展现最富有生命力的一面。你在团队写出了大家都不熟悉的方式,即使再新潮,也未见得是最富有生命力的。

NET媒体文件操作组件TagLib的更多相关文章

  1. 开源的.NET媒体文件操作组件TagLib#解析

    人生得意须尽欢 莫使金樽空对月.写博客都会在吃饭后,每次吃饭都要喝上二两小酒,写博客前都要闲扯,这些都是个人爱好,改不掉了,看不惯的人,还望多多包含一下,有相同爱好的同学,咱们可以一起喝着小酒一边吹牛 ...

  2. Mac OS环境下媒体文件分割工具mediafilesegmenter的简单使用(生成M3U8 TS文件)

    mediafilesegmenter是苹果开发的一款用于分割媒体文件的工具,其功能与mediastreamsegmenter相似,但操作更简单. * 具体可以对比博客中的另一篇简介<Mac OS ...

  3. 【转载】.NET压缩/解压文件/夹组件

    转自:http://www.cnblogs.com/asxinyu/archive/2013/03/05/2943696.html 阅读目录 1.前言 2.关于压缩格式和算法的基础 3.几种常见的.N ...

  4. 背水一战 Windows 10 (91) - 文件系统: Application Data 中的文件操作, Application Data 中的“设置”操作, 通过 uri 引用 Application Data 中的媒体

    [源码下载] 背水一战 Windows 10 (91) - 文件系统: Application Data 中的文件操作, Application Data 中的“设置”操作, 通过 uri 引用 Ap ...

  5. 免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)

    前面介绍了六种.NET组件,其中有一种组件是写文件的压缩和解压,现在介绍另一种文件的解压缩组件SharpZipLib.在这个组件介绍系列中,只为简单的介绍组件的背景和简单的应用,读者在阅读时可以结合官 ...

  6. 免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)

    在生活中有一种东西几乎已经快要成为我们的另一个电子”身份证“,那就是二维码.无论是在软件开发的过程中,还是在普通用户的日常中,几乎都离不开二维码.二维码 (dimensional barcode) , ...

  7. 一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)

    在目前的软件项目中,都会较多的使用到对文档的操作,用于记录和统计相关业务信息.由于系统自身提供了对文档的相关操作,所以在一定程度上极大的简化了软件使用者的工作量. 在.NET项目中如果用户提出了相关文 ...

  8. [.NET] 开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc

    开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc [博主]反骨仔 [原文地址]http://www.cnblogs.com/li ...

  9. Android开发7:简单的数据存储(使用SharedPreferences)和文件操作

    前言 啦啦啦~大家好,又见面啦~ 本篇博文讲和大家一起完成一个需要注册.登录的备忘录的,一起学习 SharedPreferences 的基本使用,学习 Android 中常见的文件操作方法,复习 An ...

随机推荐

  1. 关于python中矩阵的实现和矩阵的转置

    python中矩阵的实现是靠序列,,, 序列有很多形式, 其实矩阵是现实生活中的东西,把现实生活中的结构转换到程序中. 就需要有个实现的方法,而这种路径是多种多样的. 下面给出一个把矩阵转换成pyth ...

  2. pdf.js安装步骤和使用

    从github下载的源码不能直接使用,最好使用命令行下载安装 1.下载源码 git clone git://github.com/mozilla/pdf.js.git cd pdf.js 2.安装no ...

  3. Altium Designer绘制mark点

    mark注:我之前是按照下面的文章去制作的,由于头一次制作没有经验,不是很成功 文章是正确的 只是我的一些配置出错了: 先看一下我们的板子: 关于错误mark点,主要是周边又一圈亮锡,, 原因大概是敷 ...

  4. 怎样在一个fragment or 随意类中操作还有一个fragment中的方法

    1 怎样在acitivty中运行fragment中的方法: 首先获得这个Fragment的对象 xxxFragment fragmentObject = (xxxFragment) getFragme ...

  5. Spring Cloud项目

    如何使用windows版Docker并在IntelliJ IDEA使用Docker运行Spring Cloud项目   如何使用windows版Docker并在IntelliJ IDEA使用Docke ...

  6. 【Codeforces Round #439 (Div. 2) C】The Intriguing Obsession

    [链接] 链接 [题意] 给你3种颜色的点. 每种颜色分别a,b,c个. 现在让你在这些点之间加边. 使得,同种颜色的点之间,要么不连通,要么连通,且最短路至少为3 边是无向边. 让你输出方案数 [题 ...

  7. js进阶解决浏览器缓存不能自动更新的问题(在ajax的url上带上一个参数,可以是日期,或者是随机数)(随机数Math.random)(取得日期的毫秒数:new Date().getTime();)

    js进阶解决浏览器缓存不能自动更新的问题(在ajax的url上带上一个参数,可以是日期,或者是随机数)(随机数Math.random)(取得日期的毫秒数:new Date().getTime();) ...

  8. mariadb远程不能访问,出现Can't connect to MySQL server on '' (10061)

    一,现象: 1. 1 远程连接数据库mariadb时,报错 二,定位: 2. 1  首先本地连接上数据库,然后操作权限表数据 ,然后远程再次连接依然连接不上: 2. 2   搜索mariadb的配置文 ...

  9. iconv简介(1、字符串|文件字符转换:iconv用于将一种已知的字符集文件转换成另一种已知的字符集文件)(2、编程语言函数功能的相似性:iconv不仅再php中有用,而且c语言中也有用,还有linux等)

    iconv简介(1.字符串|文件字符转换:iconv用于将一种已知的字符集文件转换成另一种已知的字符集文件)(2.编程语言函数功能的相似性:iconv不仅再php中有用,而且c语言中也有用,还有lin ...

  10. c++ 成员函数指针

    C++中,成员指针是最为复杂的语法结构.但在事件驱动和多线程应用中被广泛用于调用回叫函数.在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数.在这样的应用中,如果不用成员指针,编程是非常困难 ...