c#如何从nvlc捕获音频并提高Accord.Audio.NewFrameEventArgs

时间:2018-08-12 16:19:42

标签: c# ffmpeg vlc accord.net

我正在使用c#中的应用程序来记录来自IP摄像机的视频流。

我正在使用Accord.Video.FFMPEG.VideoFileWriter和nVLC C#包装器。 我有一个使用nVLC捕获流中音频的类,该类应实现IAudioSource接口,因此我使用CustomAudioRendere捕获声音数据,然后引发了包含信号对象的事件Ne​​wFrame。 问题是,将信号保存到视频文件时,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;
        }
    }

1 个答案:

答案 0 :(得分:0)

我已经通过从SoundCallback中的Sound对象“ newSound”中仅获取一个通道来解决此问题,然后从该字节数组中创建了一个信号并引发了事件“ NewFrame”。 此解决方案的主要思想是,当音频流包含多个声道时,SoundCallback void中Sound对象中的SampleData属性通过以下形式包含所有声道的字节数组: 让我们假设一个通道的声音数据是两个字节的采样是A1A2B1B2C1C2 ...等等,因此SampleData将用于两个通道,如下所示: A1A2A1A2B1B2B1B2C1C2C1C2 .....等。

希望可以帮到您。