开源的.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. amazeui学习笔记--css(基本样式2)--基础设置Base

    amazeui学习笔记--css(基本样式2)--基础设置Base 一.总结 1.盒子模型:外margin,内padding,这里的内外指的边框 2.border-box:Amaze UI 将所有元素 ...

  2. (转)linux screen 命令详解

    转自:http://www.cnblogs.com/mchina/archive/2013/01/30/2880680.html 一.背景 系统管理员经常需要SSH 或者telent 远程登录到Lin ...

  3. Day2:字符串常用方法

    字符串常用方法 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Hiuhung Wan name = "my \tname is ...

  4. VS2012载入DLL编译出现试图载入格式不对的程序; 以及执行出现Mixed mode assembly is built against version &#39;v2.0.50727&#39; of the

    VS2012载入DLL编译出现试图载入格式不对的程序:以及执行出现Mixed mode assembly is built against version 'v2.0.50727' of therun ...

  5. Scala基础知识(二)

    1.条件表达式 object ConditionDemo { def main(args: Array[String]) { val x = //判断x的值,将结果赋给y val y = ) //打印 ...

  6. 【例题 6-10 UVA - 699】The Falling Leaves

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 递归模拟就好. [代码] #include <bits/stdc++.h> using namespace std; c ...

  7. imresize() 函数——matlab

    功能:改变图像的大小. 用法:B = imresize(A,m)B = imresize(A,m,method)B = imresize(A,[mrows ncols],method) B = imr ...

  8. [Immutable.js] Updating nested values with ImmutableJS

    The key to being productive with Immutable JS is understanding how to update values that are nested. ...

  9. js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用)

    js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用) 一.总结 2.匿名函数作为参数传递 二.js进阶ajax函数封装 ajax1.js function ajax(ur ...

  10. 百度地图 layer弹出地图 获取坐标

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...