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

c# how to capture audio from nvlc and raise Accord.Audio.NewFrameEventArgs

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

我正在使用 Accord.Video.FFMPEG.VideoFileWriter 和 nVLC C# 包装器。 我有一个 class 使用 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;
        }
    }

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

希望对您有所帮助。