ハードウェアの制限により、当社が作成するソフトウェアは、ライブラリにインポートするオーディオ ファイル (ハードウェアにコピーする準備ができている) が許容可能なビット レートであることを確認しようとします。
最近、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 のアドバイスに従って、各ファイルの 16 進数の ID3 タグの違いを調べてきました。これは私が見つけたものです:
初期入力は ID3v2.3 です。FFmpeg で再エンコードすると、ID3 データは v2.4 になります。この再エンコードされた最初のファイルは、メディア プレーヤーと当社のソフトウェアで正常に再生されます。当社のソフトウェアで TagLib# を使用してアルバム アートを追加すると、ID3v2.4 が保持されますが、タグは TagLib# を使用して読み取られ、Windows Media Player などのメディア プレーヤーでのみ再生されます。別のツールを使用して ID3 タグ (この場合は AudioShell Tag Editor) を変更し、同じアルバム アートを追加すると、ID3 バージョンが 2.3 に変更され、mp3 がソフトウェア オーディオ プレーヤーや他のメディア プレーヤーで再生されるようになりました - ただし、タグを変更するその後、画像を保存するときに例外が発生します。
私が試したもう 1 つのことは、再エンコード後に ID3v2.4 ブロックを完全に取り除くことでした。これは (ご想像のとおり) すべてのメディア プレーヤーで再生されます。このタグなしファイルで TagLib# を使用すると、タグが正しく適用され (v2.3)、当社のソフトウェアと他のソフトウェアで引き続き適切に再生されました。
誰かがエレガントな解決策を提案できない限り (TagLib# に新しい ID3v2.3 ブロックを強制的に書き込むか、FFmpeg にまったく書き込みを停止させる)、エンコード後にファイルから ID3v2.4 ブロックをプログラムで削除してから、新しいもの。