问题描述
由于硬件限制,我们生产的软件尝试确保将其导入到其库中的任何音频文件(准备复制到硬件中)是可接受的比特率。
最近我们开始使用FFmpeg将许多不同的音频类型转换为mp3,以便在我们的硬件上导入和使用它们。虽然转换工作正常,mp3文件在我们的硬件上工作,但是当将专辑封面添加到mp3的ID3标签时,我们就会遇到问题。该曲目不会在我们的软件中播放音频。似乎Windows无法在资源管理器中拿起ID3标签的值,但是Windows Media Player仍然会播放曲目。
这个问题只是在更改使用FFmpeg后,新转换的mp3s'ID3标签。从其他来源或已经拥有ID3标签专辑封面的MP3更改标签是很好的。
从我们的软件使用FFmpeg的代码如下:
private const string SAMPLE_RATE =44100;
...
//为输出创建临时文件
outFile = Path.GetTempFileName();
outFile = Path.ChangeExtension(outFile,mp3);
if(!File.Exists(inFile))
return false;
string metadata =(inFile.EndsWith(mp3))? :-map_meta_data 0:0;
//构建过程
string workingDirectory = Environment.CurrentDirectory;
ProcessStartInfo FFmpegProcessInfo = new ProcessStartInfo();
FFmpegProcessInfo.WorkingDirectory = workingDirectory;
FFmpegProcessInfo.FileName =ffmpeg.exe;
FFmpegProcessInfo.Arguments =-i \+ inFile +\+-ar+ SAMPLE_RATE + metadata +\+ outFile +\; //默认转换为SAMPLE_RATE
FFmpegProcessInfo.CreateNoWindow = true; //隐藏用户
//让我们抓住输出
FFmpegProcessInfo.RedirectStandardError = true;
FFmpegProcessInfo.RedirectStandardOutput = true;
FFmpegProcessInfo.UseShellExecute = false;
进程p = Process.Start(FFmpegProcessInfo);
要更改ID3标签,我们已经开始使用TagLib-Sharp,用于更改ID3标签的代码是:
public void SetId3Tags(string path,Bitmap image,IDictionary< string,string> values)
{
FileInfo fileInfo = new FileInfo(path);
fileInfo.Attributes = FileAttributes.Normal;
try
{
TagLib.File tagFile = TagLib.File.Create(path);
if(values.ContainsKey(Title))
tagFile.Tag.Title = values [Title];
if(values.ContainsKey(Artist))
tagFile.Terformers = new string [1] {values [Artist]};
if(values.ContainsKey(Comments))
tagFile.Tag.Comment = values [Comments];
if(image!= null){
string tmpImg = Path.GetTempFileName();
image.Save(tmpImg);
IPicture newArt = new Picture(tmpImg);
tagFile.Tag.Pictures = new IPicture [1] {newArt};
}
tagFile.Save();
}
catch(异常e)
{
_logger.Log(e);
}
}
用于在软件中播放曲目的代码(QuartzTypeLib中的FilgraphManager):
public void Play()
{
if(!_isPaused)
{
_graphManager = new FilgraphManager();
_mp3control =(IMediaControl)_graphManager;
_mp3position =(IMediaPosition)_graphManager;
_tempFile = Path.GetTempFileName();
File.Copy(_fullPath,_tempFile,true);
_mp3control.RenderFile(_tempFile);
}
else
{
_isPaused = false;
}
_mp3control.Run();
}
执行 _mp3control.RenderFile(_tempFile )
:
{System.Runtime.InteropServices.ExternalException} = {HRESULT的异常:0x80040266 }
在QuartzTypeLib.FilgraphManagerClass.RenderFile(String strFilename)
我这里最大的问题是我不知道这个错误在于(我们实施的)FFmpeg(在许多其他地方使用的大型图书馆),TagLib-Sharp或音频播放。
编辑1:遵循J. Andrew Laughlin的建议,我一直在看每个文件的十六进制ID3标签的差异。这是我发现的:
初始输入是ID3v2.3。使用FFmpeg进行重新编码后,ID3数据为v2.4。这个初始重新编码的文件在媒体播放器和我们的软件中播放正常。在我们的软件中使用TagLib#添加专辑封面保持ID3v2.4,但标签只能使用TagLib#读取它们,并且只能播放在Windows Media Player等媒体播放器中。使用另一个工具来更改ID3标签(在这种情况下是AudioShell标签编辑器),并添加相同的专辑封面将ID3版本更改为2.3,意味着mp3在我们的软件音频播放器以及其他媒体播放器上播放 - 但是更改标签之后,在保存图像时会产生异常。
我尝试的另一件事是在重新编码后彻底翻出ID3v2.4块,这样播放在所有的媒体播放器中都有。当在这个未标记的文件上使用TagLib#时,这些标签被正确应用(v2.3),并且在我们的软件以及其他软件中继续播放。
除非任何人都可以建议一个优雅的解决方案(强制TagLib#编写一个新的ID3v2.3块或者停止FFmpeg写入一个)我想我可能只是编程后从文件中删除ID3v2.4块,然后写一个新的一个。
TagLib#可用于将ID3标签从2.4降级到2.3。我个人更喜欢将我的ID3标签转换为2.3,因为它更符合音乐播放器的要求。
已经有一段时间了,但我相信你可以在你的以上代码:
TagLib.Id3v2.Tag id3v2tag = tagFile.GetTag(TagLib.TagTypes.Id3v2,false);
if(id3v2tag!= null)
id3v2tag.Version = 3;
tagFile.Save();
或者,您可以通过在应用程序初始化时使用以下代码强制所有标签在2.3中呈现:
TagLib.Id3v2.Tag.DefaultVersion = 3;
TagLib.Id3v2.Tag.ForceDefaultVersion = true;
TagLib#也可以完全删除标签并重新添加标签,但不一定要来
祝你好运!
Due to hardware restrictions, the software we produce tries to ensure that any audio file it imports into it's library (ready to be copied onto the hardware) is an acceptable bit rate.
Recently we've started using FFmpeg to convert a number of different audio types to mp3 to allow them to be imported and used on our hardware. Whilst the conversion works fine and the mp3 files work on our hardware afterwards, we're having issues specifically when adding an album art to the ID3 tags of the mp3. The track will not play audio in our software. It also seems that Windows cannot pick up the values of the ID3 tags in explorer, but Windows Media Player will still play the track.
This problem only seems to occur when changing a newly converted mp3s' ID3 tags after using FFmpeg. Changing tags on mp3s from other sources or those that have already got ID3 tag album art is fine.
The code for using FFmpeg from our software is as follows:
private const string SAMPLE_RATE = "44100";
...
//create temp file for output
outFile = Path.GetTempFileName();
outFile = Path.ChangeExtension(outFile, "mp3");
if (!File.Exists(inFile))
return false;
string metadata = (inFile.EndsWith("mp3")) ? " " : " -map_meta_data 0:0 ";
//build process
string workingDirectory = Environment.CurrentDirectory;
ProcessStartInfo FFmpegProcessInfo = new ProcessStartInfo();
FFmpegProcessInfo.WorkingDirectory = workingDirectory;
FFmpegProcessInfo.FileName = "ffmpeg.exe";
FFmpegProcessInfo.Arguments = "-i \"" + inFile + "\"" + " -ar "+SAMPLE_RATE + metadata + "\"" + outFile + "\""; //default conversion to SAMPLE_RATE
FFmpegProcessInfo.CreateNoWindow = true; //hide from user
//let us grab the output
FFmpegProcessInfo.RedirectStandardError = true;
FFmpegProcessInfo.RedirectStandardOutput = true;
FFmpegProcessInfo.UseShellExecute = false;
Process p = Process.Start(FFmpegProcessInfo);
To change the ID3 tags we have started using TagLib-Sharp and the code for changing the ID3 tags is:
public void SetId3Tags(string path, Bitmap image, IDictionary<string, string> values)
{
FileInfo fileInfo = new FileInfo(path);
fileInfo.Attributes = FileAttributes.Normal;
try
{
TagLib.File tagFile = TagLib.File.Create(path);
if (values.ContainsKey("Title"))
tagFile.Tag.Title = values["Title"];
if (values.ContainsKey("Artist"))
tagFile.Tag.Performers = new string[1] { values["Artist"] };
if (values.ContainsKey("Comments"))
tagFile.Tag.Comment = values["Comments"];
if (image != null) {
string tmpImg = Path.GetTempFileName();
image.Save(tmpImg);
IPicture newArt = new Picture(tmpImg);
tagFile.Tag.Pictures = new IPicture[1] {newArt};
}
tagFile.Save();
}
catch (Exception e)
{
_logger.Log(e);
}
}
And the code used to play the track in the software (FilgraphManager in QuartzTypeLib):
public void Play()
{
if (!_isPaused)
{
_graphManager = new FilgraphManager();
_mp3control = (IMediaControl)_graphManager;
_mp3position = (IMediaPosition)_graphManager;
_tempFile = Path.GetTempFileName();
File.Copy(_fullPath, _tempFile, true);
_mp3control.RenderFile(_tempFile);
}
else
{
_isPaused = false;
}
_mp3control.Run();
}
And the error when executing _mp3control.RenderFile(_tempFile)
:
{System.Runtime.InteropServices.ExternalException} = {"Exception from HRESULT: 0x80040266"}
at QuartzTypeLib.FilgraphManagerClass.RenderFile(String strFilename)
My largest problem here is that I don't know whether the fault lies with (our implementation of) FFmpeg (large library that's used fine in many other places), TagLib-Sharp or the audio playing.
Edit 1: Following J. Andrew Laughlin's advice I've been looking at the differences of the ID3 tags in the hex of each file. This is what I've found:
The initial input is ID3v2.3. After re-encoding with FFmpeg, the ID3 data is v2.4. This initial re-encoded file plays fine in media players and our software. Using TagLib# in our software to add album art keeps ID3v2.4 but the tags are only available using TagLib# to read them and it only plays in media players such as Windows Media Player. Using another tool to change the ID3 tags (in this case AudioShell Tag Editor) and add the same album art changed the ID3 version to 2.3 and meant that the mp3 played on our softwares audio player as well as other media players - However changing the tags afterwards produces an exception when saving the image.
One other thing I tried was to rip out the ID3v2.4 block completely after the re-encoding, this plays (as you'd expect) in all media players. When using the TagLib# on this untagged file, the tags were correctly applied (v2.3) and it continued to play properly in our software as well as others.
Unless anyone can suggest an elegant solution (either force TagLib# to write a new ID3v2.3 block or stop FFmpeg from writing one at all) I think I may just programmatically remove the ID3v2.4 block from the file after encoding and then write a new one.
TagLib# can be used to "downgrade" an ID3 tag from 2.4 to 2.3. I personally prefer to convert my ID3 tags to 2.3 since it is more consistently adopted across music players.
It's been a while, but I believe you can use the following in your above code:
TagLib.Id3v2.Tag id3v2tag = tagFile.GetTag(TagLib.TagTypes.Id3v2, false);
if(id3v2tag != null)
id3v2tag.Version = 3;
tagFile.Save();
Alternatively, you can force all tags to render in 2.3 by using the following code when your application initializes:
TagLib.Id3v2.Tag.DefaultVersion = 3;
TagLib.Id3v2.Tag.ForceDefaultVersion = true;
TagLib# can also remove tags completely and re-add them, but it shouldn't have to come to that.
Good luck!
这篇关于在id3图像编辑后麻烦播放mp3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!