精华内容
下载资源
问答
  • webrtc混音混流

    2020-11-28 10:29:13
    webRTC混音流程 https://blog.csdn.net/u013692429/article/details/100778297 原因:由于目前开始调研混音算法,故在此分析一下webRTC的实现流程,其他实现流程在另外一个博客有记录. 概况:目前调研的混音...

    webRTC混音流程

    https://blog.csdn.net/u013692429/article/details/100778297

     

    原因:由于目前开始调研混音算法,故在此分析一下webRTC的实现流程,其他实现流程在另外一个博客有记录.

    概况:目前调研的混音算法在多路混音时只有webRtc的原理符合基本流程。webRtc充分考虑了人耳在同一时间内最多只能感知3路音频的特性,故在多路混音时选择三路能力值最大的作为主要混音,其余参与者判断是否上一帧参与过混音,如果参与过则当前帧进行淡出特性,然后一起进行混音.而最终的混音算法就是简单的线性叠加做饱和运算.

    代码分析:

    主要实现文件在webrtc/modules/audio_conference_mixer目录.依赖的头文件主要有audio_conference_mixer_defines.h,该文件中主要定义了MixerParticipan和AudioMixerOutputRecevier两个类,该两个类主要定义了混音数据的对象来源和混音后数据的接收.调用逻辑通过TimeUnitNextProcess和Process方法进行调用,所以重点实现在process方法中.主要方法伪代码如下:

     

     

    https://www.cnblogs.com/Yinkaisheng/p/11105005.html

    展开全文
  • webRTC混音流程

    2019-09-12 17:25:51
    原因:由于目前开始调研混音算法,故在此分析一下webRTC的实现流程,其他实现流程在另外一个博客有记录. 概况:目前调研的混音算法在多路混音时只有webRtc的原理符合基本流程。webRtc充分考虑了人耳在同一时间内...

    原因:由于目前开始调研混音算法,故在此分析一下webRTC的实现流程,其他实现流程在另外一个博客有记录.

    概况:目前调研的混音算法在多路混音时只有webRtc的原理符合基本流程。webRtc充分考虑了人耳在同一时间内最多只能感知3路音频的特性,故在多路混音时选择三路能力值最大的作为主要混音,其余参与者判断是否上一帧参与过混音,如果参与过则当前帧进行淡出特性,然后一起进行混音.而最终的混音算法就是简单的线性叠加做饱和运算.

    代码分析:

    主要实现文件在webrtc/modules/audio_conference_mixer目录.依赖的头文件主要有audio_conference_mixer_defines.h,该文件中主要定义了MixerParticipan和AudioMixerOutputRecevier两个类,该两个类主要定义了混音数据的对象来源和混音后数据的接收.调用逻辑通过TimeUnitNextProcess和Process方法进行调用,所以重点实现在process方法中.主要方法伪代码如下:

    void AudioConferenceMixerImpl::Process() {
    
      UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap,
                        &remainingParticipantsAllowedToMix);
    
        MixFromList(mixedAudio, mixList);
        MixAnonomouslyFromList(mixedAudio, additionalFramesList);
        MixAnonomouslyFromList(mixedAudio, rampOutList);
    
    
    }

    UpdateToMix是为了将参与会话成员按需求分配到mixList,rampOutList,mixList就是重点需要进行mix的会话成员,而rampOutList是上一帧参与会话,当前帧将该会话进行淡出处理,所以重点分析UpdateToMix方法代码如下:通过代码可以看出首先进行判断当前会话上一帧是否参与了mix,如果没有则将进行RampIn特效处理,然后加入activeList队列,在加入过程前判断队列是否达到了限制的最大值,如果达到则将移除能量值最小的会话成员,而在移除过程中也要判断移除的会话成员上一帧是否参与了mix,如果参与了则将该会话当前帧做RampOut处理.

    void AudioConferenceMixerImpl::UpdateToMix(
        AudioFrameList* mixList,
        AudioFrameList* rampOutList,
        std::map<int, MixerParticipant*>* mixParticipantList,
        size_t* maxAudioFrameCounter) const {
    
    
     for (MixerParticipantList::const_iterator participant =
            _participantList.begin(); participant != _participantList.end();
             ++participant) {
    
    
       if(audioFrame->vad_activity_ == AudioFrame::kVadActive) {
                if(!wasMixed && !muted) {
                    RampIn(*audioFrame);
                }
    
            if(activeList.size() >= *maxAudioFrameCounter) {
            
               if (replaceWasMixed) {
                          if (!replaceFrame.muted) {
                            RampOut(*replaceFrame.frame);
                          }
                          rampOutList->push_back(replaceFrame);
    
            }
                
        }
    
    
    }

    最后将当前两个队列成员进行mix处理.主要代码如下:可以看出进行了简单的合并.

    void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) {
    
    
      if (use_limiter) {
        // This is to avoid saturation in the mixing. It is only
        // meaningful if the limiter will be used.
        AudioFrameOperations::ApplyHalfGain(frame);
      }
      if (mixed_frame->num_channels_ > frame->num_channels_) {
        // We only support mono-to-stereo.
        assert(mixed_frame->num_channels_ == 2 &&
               frame->num_channels_ == 1);
        AudioFrameOperations::MonoToStereo(frame);
      }
    
    }
    
    void AudioFrameOperations::Add(const AudioFrame& frame_to_add,
                                   AudioFrame* result_frame) {
    for (size_t i = 0;
             i < result_frame->samples_per_channel_ * result_frame->num_channels_;
             i++) {
          const int32_t wrap_guard = static_cast<int32_t>(result_frame->data_[i]) +
                               static_cast<int32_t>(frame_to_add.data_[i]);
          result_frame->data_[i] = rtc::saturated_cast<int16_t>(wrap_guard);
    
    }

    按照webRTC混音原理通过简单代码实现,4路进行混音最终生成的波形如下

    利用FFmpeg命令行生成如下:可以明显看出波形衰减严重。

    总结:webRTC混音原理通过代码可以大体分析出,可以根据原理自己实现一个混音算法。

    展开全文
  • WebRTC 混音分析

    2018-05-04 21:12:51
    webrtc网站被和谐, 直接上github查找有没有人fork, 然后找到一个比较新的版本 ...没有下载代码, 直接用手机在网页上查看代码, 虽然不方便,但也找到混音处理代码. 简单写一下大概过程, 详细的在以后有用到...

    webrtc网站被和谐, 直接上github查找有没有人fork, 然后找到一个比较新的版本
    https://github.com/JumpingYang001/webrtc
    https://github.com/ibaoger/webrtc (这个好像每天都更新)

    没有下载代码, 直接用手机在网页上查看代码, 虽然不方便,但也找到混音处理代码.
    简单写一下大概过程, 详细的在以后有用到时再研究吧。
    因为是在手机上看的代码,可能理解有误,等有空再仔细在电脑上深入研究。

    混音对象:

    media/engie/webrtcvoiceengine.cc
    void WebRtcVoiceEngine::Init() {
    ...
    config.audio_mixer = webrtc::AudioMixerImpl::Create();
    ...
    }

    混音类:

    modules/audio_mixer/audio_mixer_impl.cc
    AudioMixerImpl::Mix()

    Mix方法调用:

    modules/audio_mixer/frame_combiner.cc
    FrameCombiner::Combine()

    Combine方法:
    调用MixToFloatFrame进行合并, MixToFloatFrame只是简单的把数据相加, 然后调用RunApmAgcLimiter或RunApmAgc2Limiter对混音结果进行增益处理, 同时应该可以防止溢出.
    调用InterleaveToAudioFrame根据音频声道交织处理混音结果.
    最后混音的结果在audio_frame_for_mixing中.

    展开全文
  • WebRTC混音流程分析

    千次阅读 2019-01-14 10:00:51
    混音分为服务端混音和客户端混音两种,服务端混音是为了节省带宽。...WebRTC中目前只有客户端混音混音具体实现在webrtc/modules/audio_conference_mixer目录中 想知道一个C++模块如何使用,我们一...

    混音分为服务端混音和客户端混音两种,服务端混音是为了节省带宽。哪为什么客户端也要混音呢?哪是国为声卡同一时刻只能播放一路
    语音,当你的客户端有多路接收语音时,如果你不先混音,而是每一路都直接住声卡送的话,容易会造成声音越来越延时。

    WebRTC中目前只有客户端混音,混音具体实现在webrtc/modules/audio_conference_mixer目录中
    想知道一个C++模块如何使用,我们一般会先看看这个模块的头文件,在audio_conference_mixer模块的include目录下有两个头文件
    audio_conference_mixer.h 和 audio_conference_mixer_defines.h,我们先来看看audio_conference_mixer_defines.h,在这个文件
    中定义了两个类
    MixerParticipant:被混音方,负责给混音器提供原始语音数据
    AudioMixerOutputReceiver:混音后的语音接收方

    在audio_conference_mixer.h文件中定义了AudioConferenceMixer类,它继承于Module类,说明这个类的对象可以被WebRTC的工作线
    程周期性的调用。在这个类定义中,

    被混音方的添加和删除用SetMixabilityStatus(MixerParticipant* participant,bool mixable)方法来实现,这个方法中
    第一个参数是被混音对象指针,第二个参数是是否能被混音。

    添加接收方使用RegisterMixedStreamCallback(AudioMixerOutputReceiver* receiver),参数代表接收者对象
    另外我们还发现这两个方法
    // Module functions
    int64_t TimeUntilNextProcess() override = 0;
    void Process() override = 0;

    从上面几个方法,我们就可能想象出这个混音模块大概的工作流程,WebRTC工作线程先调用混音模块的TimeUntilNextProcess方法,先确认是否到了处理
    这个模块的时间,如果还没有到时间,就直接处理下一个模块 ,如果到了时间,就调用这个模块的Process方法,在Process方法中,会从所有的等待混音对象
    中分别取出一个音频帧,再把所有的音频帧叠加起来,合成一个音频帧,再送给混音接收对象。

    为了验证我们的想法,我们先在模块中搜索TimeUntilNextProcess和Process方法,发现这两个方法的具体实现在AudioConferenceMixerImpl类中
    在AudioConferenceMixerImpl.cc 182行AudioConferenceMixerImpl::TimeUntilNextProcess方法中,我们可以知道这这个模块以10ms的周期被
    调用,这和WebRTC的音频采样周期刚好符合。

    我们先来分析一下AudioConferenceMixerImpl::Process:下面我会以中文的方式把Process的流程写出来,大家再对照代码自己再体会一下。
    void AudioConferenceMixerImpl:rocess() {
    1,更新_timeScheduler,作用是确保以近似10ms的间隔去音频缓冲队列取数据来混音
    2,定义了三个AudioFrameList音频帧队列,mixList,rampOutList,additionalFramesList,这三个队列分别是当前需要混音的音频队列,上次已经被混音,
          这次需要被移除队列,附加的音频队列(在WebRTC中,主要用于文件播放器)
    3,分别取数据填充这三个队列,
    UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap,&remainingParticipantsAllowedToMix);
    GetAdditionalAudio(&additionalFramesList);
    4,把这三个队列混音
          MixFromList(mixedAudio, mixList);
          MixAnonomouslyFromList(mixedAudio, additionalFramesList);
                   MixAnonomouslyFromList(mixedAudio, rampOutList);
            5,  调用WebRTC中的AudioProcessing模块处理混音后的音频帧,调整音量 LimitMixedAudio(mixedAudio);
            6,通知混音接收方 _mixReceiver->NewMixedAudio
            7,清除数据
    }

    Process()方法结构还比较清晰,理解起来不太难。UpdateToMix方法主要作用是从众多候选者中选出声音最大的三个,从这三个候选者中取出音频,再混音。
    因为同时混太多路,容易发生重叠,造成语音不清楚。下面我们来分析UpdateToMix方法,UpdateToMix方法代码比较长,第一次看有点费力。

    void AudioConferenceMixerImpl::UpdateToMix(
        AudioFrameList* mixList,
        AudioFrameList* rampOutList,
        std::map<int, MixerParticipant*>* mixParticipantList,
        size_t* maxAudioFrameCounter) const {
    const size_t mixListStartSize = mixList->size();  //一直为0,不知道是不是bug
    AudioFrameList activeList;   //声音最大的用户,最多三个
    ParticipantFrameStructList passiveWasNotMixedList; //虽然没有说话,但是因为当前用户少于3,也要被混音
    ParticipantFrameStructList passiveWasMixedList; //上一次已经被混音了,这一次没有说话的用户
    for{
    1,循环从候选用户取出音频帧
    2,如果当前总用户数少于3,设置标志位mustAddToPassiveList,即使这个音频帧不是活动的,也可以被混音
    3,检测上一次是不是已经被混音,设置标志位wasMixed
    if(音频帧是活动的){
    下面代码是检测出最大的三个用户出来
    }else{
    if(上次被混音过){
    添加到passiveWasMixedList
    }else if(用户总数小于3,必需要被混音){
    添加RampIn,类似图片切换淡入淡出效果
    添加到passiveWasNotMixedList
    }else{
    直接释放不处理
    }
    }
    }
    }

    这里需要单独说明的是,WebRTC处理被混音用户进入和退出时加了特效,要不然就会太生硬了,具体实现在audio_frame_manipulator.cc文件中。当用户第一次进入时,会添加RampIn效果,当用户退出时,会加入RampOut效果。为了避免混音后的音量忽大忽小,调用了AudioProcessing模块的AGC功能,这样就可能保证音频的音量保持稳定。

    两个音频帧的混音具体实现在
    void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) {
      assert(mixed_frame->num_channels_ >= frame->num_channels_);
      if (use_limiter) {
        // Divide by two to avoid saturation in the mixing.
        // This is only meaningful if the limiter will be used.
        *frame >>= 1;
      }
      if (mixed_frame->num_channels_ > frame->num_channels_) {
        // We only support mono-to-stereo.
        assert(mixed_frame->num_channels_ == 2 &&
               frame->num_channels_ == 1);
        AudioFrameOperations::MonoToStereo(frame);
      }

      *mixed_frame += *frame;
    }
    从*mixed_frame += *frame;这一行我们可以看出AudioFrame类重定义了+=运算符,我们转到AudioFrame类去看看两个音频帧是如何混合在一起的

    inline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) {
    ...

    for (size_t i = 0; i < samples_per_channel_ * num_channels_; i++) {
                     int32_t wrap_guard =
                                  static_cast<int32_t>(data_) + static_cast<int32_t>(rhs.data_);
                              data_ = ClampToInt16(wrap_guard);
    }
    }

    从上面可以看出,两个音频帧的混合非常简单,只要把对应的音频数据相加就行。
    ClampToInt16这个方法是为了防止两个short类型数据相加的结果溢出。我们转到这个方法看看是如何实现的。
    inline int16_t ClampToInt16(int32_t input) {
      if (input < -0x00008000) {
        return -0x8000;
      } else if (input > 0x00007FFF) {
        return 0x7FFF;
      } else {
        return static_cast<int16_t>(input);
      }
    }
    这个算法也很简单,一目了然

    到此,WebRTC中的混音模块算是分析完了,本文是根据WebRTC56版本代码写的,其它版本可能会有不同的地方。

    原文:http://www.rtc8.com/forum.php?mod=viewthread&tid=33&extra=page%3D1
    --------------------- 
    作者:老衲不出家 
    来源:CSDN 
    原文:https://blog.csdn.net/tanningzhong/article/details/77968090 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • WebRTC中的混音算法

    2018-11-28 20:15:02
    webrtc混音算法在modules/audio_mixer/frame_combiner.cc文件的FrameCombiner::Combine()函数里 主干程序: void FrameCombiner::Combine(const std::vector&lt;AudioFrame*&gt;&amp; mix_list, ...
  • 本文简要说明最新版WebRtc AudioMixer混音流程。 本程序使用4个16KHz 单声道时长均大于10秒的Wav文件作为混音源,只合成前10秒的音频,输出也是16KHz单声道音频。 输入和输出的采样率都是16000,每10ms音频长度...
  • 混音 混音的意义就是将多个音频流混成一路音频,在Conference 的实现中有分为终端实现和服务器实现。 1. 终端混音实现: 终端接受到多路(一般是多个用户)的音频流之后,在终端本地将多路音频流混成一路音频送给...
  • 做录音时首先需要获取本地采集的pcm数据和所有远端用户合成后的pcm数据,也就是播放时投递给扬声器的pcm数据,本文讲解一下如何获取webrtc的原始音频数据。 ##webrtc版本说明 本文使用的webrtc api依赖于webrtc分支...
  • 一个跨平台的音频混音器,支持android、ios、macos和windows。由WebRTC、FFMPEG和吉尼提供支持。
  • WebRTC系列--录音

    2020-11-23 14:12:34
    文章目录重采样类 该篇文章主要是将WebRTC的远端和本地的音频流录制成mp3;同时也会涉及到WebRTC的重采样算法使用和混音的使用; 重采样类
  • WebRTC音频引擎的实现代码主要分布在如下几个源码目录中: ...//接收端混音 webrtc/module/audio_conference_mixer //音频输入输出设备 webrtc/module/audioDevide //音频预处理(消回音、自动增益、降噪等) webrtc/modu
  • 原因:由于需要进行基于webrtc混音模块封装,故在此进行简单调用。 概述:通过将webrtc_module_audio_conference_mixer模块的摘出,编写测试代码实现conference_mixer模块的调用,内部混音流程与之前博客分析一致...
  • WebRTC由语音引擎,视频引擎和网络传输三大模块组成,其中语音引擎是WebRTC中最具价值的技术之一,实现了音频数据的采集、前处理、编码、发送、接受、解码、混音、后处理、播放等一系列处理流程。 音频引擎主要...
  • Webrtc Intro - kurento

    千次阅读 2016-01-14 17:10:27
    折腾了一个多星期终于将kurento的环境搭建好(开发阶段的...搞视频会议就会涉及一对多、多对多、广播、转码、混音、合屏、录制,这就需要用到流媒体服务器,而kurento就具有这些功能。 他主要用来作为webrtc的流媒体
  • 在研究WebRTC服务端画面合成和混音处理,需要实现浏览器端与服务器端的点对点,网上找了好些参考的项目,webrtc2sip项目就是其中之一,该项目基于doubango的框架,需要自行编译搭建环境,根据webrtc2sip中的《技术...
  • webrtc mixer源码分析

    2021-01-20 10:39:20
    AudioMixer的入口函数为AudioMixerImpl::Mix,功能分为三步: 计算输出采样率:CalculateOutputFrequency ...混音:FrameCombiner::Combine 下面分别对这三步进行分析 CalculateOutputFrequency, ...
  • 可以通过设备端摄像头的rtsp/rtmp等流转成webrtc协议在手机app和手机浏览器和各种电脑流行浏览器网页(Chrome,edge,Firefox,safari)和pc电脑端播放,实时性在延时300毫秒左右,实现了回音消除,多路实时语言混音...

空空如也

空空如也

1 2 3
收藏数 50
精华内容 20
关键字:

webrtc混音