1.起因 同事在調用錄音控制項生成的MP3,在部分瀏覽器中載入失敗,出現彈框提示。 經過同事的對比,發現當文件屬性中比特率 為0kbps,時長為空的時候就會出現上圖這種情況。並給找到一個解決方案,使用ffmpeg進行一次轉碼後就會出現比特率和時長,瀏覽器也可以正常載入。 異常的情況 正常的情況 2.問 ...
1.起因
同事在調用錄音控制項生成的MP3,在部分瀏覽器中載入失敗,出現彈框提示。
經過同事的對比,發現當文件屬性中比特率 為0kbps,時長為空的時候就會出現上圖這種情況。並給找到一個解決方案,使用ffmpeg進行一次轉碼後就會出現比特率和時長,瀏覽器也可以正常載入。
ffmpeg.exe -i out.mp3 -b:a 128k -y -acodec libmp3lame out2.mp3 //cmd 中執行轉換命令
異常的情況 正常的情況
2.問題原因
由上面可以知道,mp3文件是由於比特率信息丟失導致的問題出現,通過查找文檔,多次修改參數試驗,問題一直存在。偶然一次再參數里設置了錄音時間,發現生成的文件時正常的。得出結論,是ffmpeg.exe沒有正常關閉導致,文件信息沒有寫完。
ffmpeg沒有正常關閉的原因,測試時候是用過關閉cmd視窗,用播放器播放mp3文件發現音頻可以正常播放,也就沒有過多思考,在代碼實現過程了,通過直接kill掉Process來實現錄製完畢。
[DllImport("kernel32.dll")] static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId); [DllImport("kernel32.dll")] static extern bool SetConsoleCtrlHandler(IntPtr handlerRoutine, bool add); [DllImport("kernel32.dll")] static extern bool AttachConsole(int dwProcessId); [DllImport("kernel32.dll")] static extern bool FreeConsole(); /// <summary> /// 功能: 停止錄製 /// </summary> public static void Stop() { try { AttachConsole(p.Id); SetConsoleCtrlHandler(IntPtr.Zero, true); GenerateConsoleCtrlEvent(0, 0); FreeConsole(); //p.Close(); if (!p.HasExited) { p.Kill(); p.WaitForExit(); } // p.Dispose(); } catch (Exception ex) { // Log.Error("關閉錄音工具ffmpeg異常", ex); } }
所以只需要正常關閉錄製就可以解決這個問題,後來發現上圖cmd界面中倒數第二行 Press [q] to stop, 試驗了下果然可以,生成的MP3也是正常的。現在只需要代碼模擬輸入q就可以解決這個問題了,
c#代碼如下
static StreamWriter myStreamWriter; /// <summary> /// 功能: 開始錄製 /// </summary> public static void Start(string audioDevice, string outFilePath) { if (File.Exists(outFilePath)) { File.Delete(outFilePath); } ProcessStartInfo startInfo = new ProcessStartInfo(ffmpegPath); startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.CreateNoWindow = true; //不加這句會顯示cmd視窗 startInfo.UseShellExecute = false; //關閉Shell的使用 startInfo.RedirectStandardOutput = true; //重定向標準輸出 startInfo.RedirectStandardInput = true; startInfo.Arguments = audioDevice; p = new Process(); p.StartInfo = startInfo; p.Start(); myStreamWriter = p.StandardInput; } /// <summary> /// 功能: 停止錄製 /// </summary> public static void Stop() { try { myStreamWriter.WriteLine("q"); Thread.Sleep(100);//q命令沒有那麼快執行 if (!p.HasExited) { p.Kill(); p.WaitForExit(); } // p.Dispose(); } catch (Exception ex) { // Log.Error("關閉錄音工具ffmpeg異常", ex); } }
分享一個錄音的測試demo https://pan.baidu.com/s/1mizerUS