c# - id3 图像编辑后播放 mp3 时遇到问题

标签 c# ffmpeg mp3 id3 taglib-sharp

由于硬件限制,我们生产的软件试图确保导入到其库中的任何音频文件(准备复制到硬件上)都是可接受的比特率。

最近,我们开始使用 FFmpeg 将多种不同的音频类型转换为 mp3,以便在我们的硬件上导入和使用它们。虽然转换工作正常并且 mp3 文件随后可以在我们的硬件上工作,但在将专辑封面添加到 mp3 的 ID3 标签时,我们遇到了问题。该轨道不会在我们的软件中播放音频。 Windows 似乎也无法在资源管理器中获取 ID3 标记的值,但 Windows Media Player 仍会播放该轨道。

此问题似乎仅在使用 FFmpeg 后更改新转换的 mp3 的 ID3 标签时才会出现。更改来自其他来源的 mp3 或已经具有 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 block ,这可以在所有媒体播放器中播放(如您所期望的)。当在此未加标签的文件上使用 TagLib# 时,标签被正确应用 (v2.3),并且它继续在我们的软件以及其他软件中正常播放。

除非有人能提出一个优雅的解决方案(要么强制 TagLib# 写入一个新的 ID3v2.3 block ,要么完全阻止 FFmpeg 写入一个),我想我可能只是在编码后以编程方式从文件中删除 ID3v2.4 block 然后写一个新的。

最佳答案

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# 还可以完全删除标签并重新添加它们,但不必这样做。

祝你好运!

关于c# - id3 图像编辑后播放 mp3 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6570840/

相关文章:

c# - 自动完成并阻止新输入 - 组合框

c# - 这个 try-catch block 有效吗?

c# - 如何在 Hudson 中自动化 Silverlight 单元测试?

ffmpeg - 如何在将流编码到 v4l2-loopback 设备时将相机录制到文件?

java - 如何将 PCM 原始数据转换为 mp3 文件?

c# - 使用 C# 添加 entityFramework 部分

php - Symfony 后台进程 FFmpeg 视频转换

react-native - 将背景中的图像和音频转换为 React Native 中的视频文件

android - 同时播放多个音频文件

android - 如何使用Android MediaPlayer在毫秒范围内播放mp3文件?