【问题标题】:c# how to capture audio from nvlc and raise Accord.Audio.NewFrameEventArgsc# 如何从 nvlc 捕获音频并引发 Accord.Audio.NewFrameEventArgs
【发布时间】:2019-01-19 11:52:08
【问题描述】:

我正在用 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;
        }
    }

【问题讨论】:

    标签: c# ffmpeg vlc accord.net


    【解决方案1】:

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

    希望能帮到你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      相关资源
      最近更新 更多