Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

这个库可以实现同时录制麦克风和电脑音频吗 #1169

Open
1592363624 opened this issue Jul 12, 2024 · 0 comments
Open

这个库可以实现同时录制麦克风和电脑音频吗 #1169

1592363624 opened this issue Jul 12, 2024 · 0 comments

Comments

@1592363624
Copy link

这个库可以实现同时录制麦克风和电脑音频吗 我的代码总是有些问题

using System;
using System.Threading.Tasks;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;

namespace CallRecording.Models
{
public class Recorder
{
private readonly object _lockObject = new();
private readonly Logger _logger;
private bool _isRecording;
private string _outputFileName;
private WaveFileWriter _waveFile;
private WasapiLoopbackCapture _systemSource;
private WaveInEvent _micSource;
private MixingSampleProvider _mixer;
private BufferedWaveProvider _systemBuffer;
private BufferedWaveProvider _micBuffer;

    public Recorder(Logger logger)
    {
        _logger = logger;
    }

    // 开始录音
    public void StartRecording(string savePath, string softwareName)
    {
        lock (_lockObject)
        {
            if (_isRecording) return;

            // 生成输出文件名
            _outputFileName = Utils.GenerateFilename(savePath, softwareName);

            // 初始化系统声音捕获
            _systemSource = new WasapiLoopbackCapture();
            _systemSource.DataAvailable += OnSystemDataAvailable;
            _systemSource.RecordingStopped += OnRecordingStopped;

            // 初始化麦克风捕获
            _micSource = new WaveInEvent();
            _micSource.DataAvailable += OnMicDataAvailable;
            _micSource.RecordingStopped += OnRecordingStopped;

            // 初始化缓冲区
            _systemBuffer = new BufferedWaveProvider(_systemSource.WaveFormat);
            _micBuffer = new BufferedWaveProvider(_micSource.WaveFormat);

            // 将输入转换为相同的WaveFormat
            var systemSampleProvider = _systemBuffer.ToSampleProvider();
            var micSampleProvider = _micBuffer.ToSampleProvider();

            // 混音器
            _mixer = new MixingSampleProvider(new[] { systemSampleProvider, micSampleProvider })
            {
                ReadFully = true
            };

            // 创建WaveFileWriter,用于写入录音文件
            _waveFile = new WaveFileWriter(_outputFileName, _mixer.WaveFormat);

            // 开始录音
            _systemSource.StartRecording();
            _micSource.StartRecording();
            _isRecording = true;

            // 记录日志
            _logger.LogMessage("开始录音...", softwareName);

            // 启动一个后台任务来写入混音数据
            Task.Run(() => WriteMixedData());
        }
    }

    // 处理系统音频数据
    private void OnSystemDataAvailable(object sender, WaveInEventArgs e)
    {
        _systemBuffer.AddSamples(e.Buffer, 0, e.BytesRecorded);
    }

    // 处理麦克风音频数据
    private void OnMicDataAvailable(object sender, WaveInEventArgs e)
    {
        _micBuffer.AddSamples(e.Buffer, 0, e.BytesRecorded);
    }

    // 后台任务写入混音数据
    private void WriteMixedData()
    {
        var buffer = new float[_mixer.WaveFormat.SampleRate * _mixer.WaveFormat.Channels];
        while (_isRecording)
        {
            int samplesRead = _mixer.Read(buffer, 0, buffer.Length);
            if (samplesRead > 0)
            {
                lock (_lockObject)
                {
                    if (_waveFile != null)
                    {
                        _waveFile.WriteSamples(buffer, 0, samplesRead);
                        _waveFile.Flush();
                    }
                }
            }
        }
    }

    // 处理录音停止事件
    private void OnRecordingStopped(object sender, StoppedEventArgs e)
    {
        lock (_lockObject)
        {
            try
            {
                _systemSource?.Dispose();
                _micSource?.Dispose();
                _waveFile?.Dispose();
                _systemSource = null;
                _micSource = null;
                _waveFile = null;

                if (e.Exception != null)
                {
                    _logger.LogMessage($"录音停止时发生异常: {e.Exception.Message}", "录音器");
                }
                else
                {
                    _logger.LogMessage($"录音已保存到: {_outputFileName}", "录音器");
                }
            }
            catch (Exception ex)
            {
                _logger.LogMessage($"在处理录音停止事件时发生异常: {ex.Message}", "录音器");
            }
        }
    }

    // 停止录音
    public void StopRecording()
    {
        lock (_lockObject)
        {
            if (!_isRecording) return;

            try
            {
                _systemSource.StopRecording();
                _micSource.StopRecording();
                _logger.LogMessage("录音停止,文件已保存。", "录音器");
            }
            catch (Exception ex)
            {
                _logger.LogMessage($"停止录音时发生异常: {ex.Message}", "录音器");
            }

            _isRecording = false;
        }
    }

    // 检查是否正在录音
    public bool IsRecording()
    {
        lock (_lockObject)
        {
            return _isRecording;
        }
    }
}

// 用于将IWaveProvider转换为WaveProvider
public class WaveInProvider : IWaveProvider
{
    private readonly IWaveIn _source;
    private readonly WaveFormat _waveFormat;
    private readonly BufferedWaveProvider _bufferedWaveProvider;

    public WaveInProvider(IWaveIn source)
    {
        _source = source;
        _waveFormat = source.WaveFormat;
        _bufferedWaveProvider = new BufferedWaveProvider(_waveFormat)
        {
            BufferLength = 10 * 1024 * 1024 // 设置为10MB的缓冲区大小
        };
        _source.DataAvailable += (s, a) => _bufferedWaveProvider.AddSamples(a.Buffer, 0, a.BytesRecorded);
    }

    public WaveFormat WaveFormat => _waveFormat;

    public int Read(byte[] buffer, int offset, int count)
    {
        return _bufferedWaveProvider.Read(buffer, offset, count);
    }
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant