在id3图像编辑后播放mp3时出现问题
本文关键字:问题 mp3 播放 id3 图像 编辑 | 更新日期: 2023-09-27 18:01:09
由于硬件限制,我们生产的软件试图确保导入其库(准备复制到硬件上(的任何音频文件都是可接受的比特率。
最近,我们开始使用FFmpeg将许多不同的音频类型转换为mp3,以便将它们导入并在我们的硬件上使用。虽然转换工作正常,mp3文件随后在我们的硬件上也能正常工作,但我们在将相册艺术添加到mp3的ID3标签时遇到了问题。该曲目将不会在我们的软件中播放音频。Windows似乎也无法在资源管理器中获取ID3标记的值,但Windows Media Player仍将播放该曲目。
这个问题似乎只有在使用FFmpeg后更改新转换的mp3的ID3标签时才会出现。更改来自其他来源或已经获得ID3标签相册艺术的MP3上的标签是可以的。
使用我们软件中的FFmpeg的代码如下:
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);
为了更改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.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);
}
}
以及用于在软件中播放曲目的代码(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} = {"Exception from HRESULT: 0x80040266"}
at 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#也可以完全删除标签并重新添加它们,但不必如此。
祝你好运!