Getting the audio waveform data of media file using ffmpeg.exe in C#
2013-12-30 10:32:51 · Author: Wudi · Tagged with: C# & .NET, Audio Processing
Previously, I use the NAudio library to implement this function. It needs to extract the audio track of a media file to a separate WAV file to deal with. Even with the help of RAM disk, the processing speed is still very slow.
Yesterday, I searched again for the usable audio processing library in C#. But there is still no better choice. Finally, the popular cross-platform command line tools mencoder, ffmpeg and so on came into my head. The ffmpeg seems to work because it support stdout output.
At first, I tried to output the binary stream in WAV format to stdout. But I found that in this situation, ffmpeg will write a placeholder for size information in head, and seek back to rewrite it after the whole stream is outputed (source). When the output target is the stdout stream instead of a file, this rewriting operation will fail, which causes the obtained WAV stream to have wrong head information and cannot be used.
The reason that I use WAV format is just because it is the most familiar audio format that storing raw waveform data. But after read the documentation of ffmpeg, I found that it supports a great many formats. It can output integers or floats directly, without head information. At last I selected the little endian 32-bit float format.
The complete code is as follows:
Yesterday, I searched again for the usable audio processing library in C#. But there is still no better choice. Finally, the popular cross-platform command line tools mencoder, ffmpeg and so on came into my head. The ffmpeg seems to work because it support stdout output.
At first, I tried to output the binary stream in WAV format to stdout. But I found that in this situation, ffmpeg will write a placeholder for size information in head, and seek back to rewrite it after the whole stream is outputed (source). When the output target is the stdout stream instead of a file, this rewriting operation will fail, which causes the obtained WAV stream to have wrong head information and cannot be used.
The reason that I use WAV format is just because it is the most familiar audio format that storing raw waveform data. But after read the documentation of ffmpeg, I found that it supports a great many formats. It can output integers or floats directly, without head information. At last I selected the little endian 32-bit float format.
The complete code is as follows:
- using System.Diagnostics;
- using System.IO;
- // ...
- static void Main(string[] args)
- {
- // ...
- string path = @"E:\Media\test.mp4";
- Process proc = new Process();
- proc.StartInfo.FileName = @"E:\ffmpeg\ffmpeg.exe";
- proc.StartInfo.Arguments = "-i \"" + path + "\" -vn -ar 44100 -ac 1 -f f32le -";
- proc.StartInfo.CreateNoWindow = true;
- proc.StartInfo.UseShellExecute = false;
- proc.StartInfo.RedirectStandardOutput = true;
- proc.StartInfo.RedirectStandardError = true;
- proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
- proc.Start();
- proc.BeginErrorReadLine();
- ProcessStream(proc.StandardOutput.BaseStream);
- proc.WaitForExit(10000); // 10s
- if (!proc.HasExited)
- {
- proc.Kill();
- Environment.Exit(1);
- }
- // ...
- }
- static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
- {
- if (e.Data != null)
- {
- // Console.WriteLine(e.Data);
- // do nothing
- }
- }
- static void ProcessStream(Stream stream)
- {
- int didread;
- int offset = 0;
- byte[] buffer = new byte[sizeof(Single) * (1024 + 1)];
- int length, residual_length;
- while ((didread = stream.Read(buffer, offset, sizeof(Single) * 1024)) != 0)
- {
- length = offset + didread;
- residual_length = length % sizeof(Single);
- if (residual_length == 0) {
- ProcessBuffer(buffer, length);
- offset = 0;
- } else {
- length -= residual_length;
- ProcessBuffer(buffer, length);
- Array.Copy(buffer, length, buffer, 0, residual_length);
- offset = residual_length;
- }
- }
- }
- static void ProcessBuffer(byte[] buffer, int length)
- {
- int index = 0;
- float sample_value;
- while (index < length)
- {
- sample_value = BitConverter.ToSingle(buffer, index);
- index += sizeof(Single);
- // to deal with sample_value
- }
- }
- // ...
请问下ffmpeg 如何计算出音频的分贝呢?
can you help me please?