我正在使用c#中的应用程序来记录来自IP摄像机的视频流。
我正在使用Accord.Video.FFMPEG.VideoFileWriter
和nVLC C#包装器。
我有一个使用nVLC捕获流中音频的类,该类应实现IAudioSource
接口,因此我使用CustomAudioRendere
捕获声音数据,然后引发了包含信号对象的事件NewFrame。
问题是,将信号保存到视频文件时,RTSP
流中的记录时声音令人恐惧(离散),而本地麦克风(来自笔记本电脑)中的记录质量却很好。
这是引发事件的代码:
public void Start()
{
_mFactory = new MediaPlayerFactory();
_mPlayer = _mFactory.CreatePlayer<IAudioPlayer>();
_mMedia = _mFactory.CreateMedia<IMedia>(Source);
_mPlayer.Open(_mMedia);
var fc = new Func<SoundFormat, SoundFormat>(SoundFormatCallback);
_mPlayer.CustomAudioRenderer.SetFormatCallback(fc);
var ac = new AudioCallbacks { SoundCallback = SoundCallback };
_mPlayer.CustomAudioRenderer.SetCallbacks(ac);
_mPlayer.Play();
}
private void SoundCallback(Sound newSound)
{
var data = new byte[newSound.SamplesSize];
Marshal.Copy(newSound.SamplesData, data, 0, (int)newSound.SamplesSize);
NewFrame(this, new Accord.Audio.NewFrameEventArgs(new Signal(data,Channels, data.Length, SampleRate, Format)));
}
private SoundFormat SoundFormatCallback(SoundFormat arg)
{
Channels = arg.Channels;
SampleRate = arg.Rate;
BitPerSample = arg.BitsPerSample;
return arg;
}
这是捕获事件的代码:
private void source_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Signal sig = eventArgs.Signal;
duration += eventArgs.Signal.Duration;
if (videoFileWrite == null)
{
videoFileWrite = new VideoFileWriter();
videoFileWrite.AudioBitRate = sig.NumberOfSamples*sig.NumberOfChannels*sig.SampleSize;
videoFileWrite.SampleRate = sig.SampleRate;
videoFileWrite.FrameSize = sig.NumberOfSamples/sig.NumberOfFrames;
videoFileWrite.Open("d:\\output.mp4");
}
if (isStartRecord)
{
DoneWriting = false;
using (MemoryStream ms = new MemoryStream())
{
encoder = new WaveEncoder(ms);
encoder.Encode(eventArgs.Signal);
ms.Seek(0, SeekOrigin.Begin);
decoder = new WaveDecoder(ms);
Signal s = decoder.Decode();
videoFileWrite.WriteAudioFrame(s);
encoder.Close();
decoder.Close();
}
DoneWriting = true;
}
}
答案 0 :(得分:0)
我已经通过从SoundCallback中的Sound对象“ newSound”中仅获取一个通道来解决此问题,然后从该字节数组中创建了一个信号并引发了事件“ NewFrame”。 此解决方案的主要思想是,当音频流包含多个声道时,SoundCallback void中Sound对象中的SampleData属性通过以下形式包含所有声道的字节数组: 让我们假设一个通道的声音数据是两个字节的采样是A1A2B1B2C1C2 ...等等,因此SampleData将用于两个通道,如下所示: A1A2A1A2B1B2B1B2C1C2C1C2 .....等。
希望可以帮到您。