ffmpeg混音(将多个声音合成一个)命令


ffmpeg命令中可以使用filter amix实现这个功能。

官方文档

http://ffmpeg.org/ffmpeg-filters.html 
6.8 amix 
Mixes multiple audio inputs into a single output.

Note that this filter only supports float samples (the amerge and pan audio filters support many formats). If the amix input has integer samples then aresample will be automatically inserted to perform the conversion to float samples.

For example

ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT 
will mix 3 input audio streams to a single output with the same duration as the first input and a dropout transition time of 3 seconds.

It accepts the following parameters:

inputs 
The number of inputs. If unspecified, it defaults to 2.

duration 
How to determine the end-of-stream.

longest 
The duration of the longest input. (default)

shortest 
The duration of the shortest input.

first 
The duration of the first input.

dropout_transition 
The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds.

例子

把当前电脑播放的声音混合到文件中的例子(”audio=”后面是音频设备名,ffmpeg -f dshow -list_devices 1 -i dummy可以在win下获取音频设备名):

ffmpeg.exe -re -i 1234.mp4 -f dshow -i audio=”立体声混音 (Realtek High Definition ” -filter_complex amix=inputs=2:duration=first:dropout_transition=0 -t 10 out.mp4 -y


pcm混音的原理是把两组数据相加,相加后的数据范围不能超过pcm位宽的表示范围,MixFrames写死是int16_t类型(具体查看AudioFrame),所以可以看出webrtc内混音处理是不支持16bit之外的pcm音频。

PCM操作,包括单声道转立体声、立体声转单声道、哑音、音量调整。 
音频术语

webrtc中的混音函数在webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc,也就是下面这个函数。

// Mix |frame| into |mixed_frame|, with saturation protection and upmixing.
// These effects are applied to |frame| itself prior to mixing. Assumes that
// |mixed_frame| always has at least as many channels as |frame|. Supports
// stereo at most.
//
// TODO(andrew): consider not modifying |frame| here.
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;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

最后一句代码才是混合的关键所在,它调用了AudioFrame的重载函数+=,也就是进行了下面的操作。也就是把相加后的数据控制在int16_t范围。 
文件路径是:webrtc/modules/interface/module_common_types.h

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

  if (speech_type_ != rhs.speech_type_) speech_type_ = kUndefined;

  if (noPrevData) {
    memcpy(data_, rhs.data_,
           sizeof(int16_t) * rhs.samples_per_channel_ * num_channels_);
  } else {
    // IMPROVEMENT this can be done very fast in assembly
    for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
      int32_t wrapGuard =
          static_cast<int32_t>(data_[i]) + static_cast<int32_t>(rhs.data_[i]);
      if (wrapGuard < -32768) {
        data_[i] = -32768;
      } else if (wrapGuard > 32767) {
        data_[i] = 32767;
      } else {
        data_[i] = (int16_t)wrapGuard;
      }
    }
  }
  energy_ = 0xffffffff;
  return *this;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

最后的判断可以用宏来写

#define MIXER_MAX(x,y) ((x)>(y)? (x):(y))
#define MIXER_MIN(x,y) ((x)<(y)? (x):(y))
#define MIXER_CLIP3(a,b,x) (MIXER_MAX(a,MIXER_MIN(x,b)))  /* clip x between a and b */
#define MIXER_CLIP(x)  MIXER_CLIP3(-32768,32767,x)

for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
    int32_t wrapGuard =
        static_cast<int32_t>(data_[i]) + static_cast<int32_t>(rhs.data_[i]);
    data_[i] = (int16_t)MIXER_CLIP(wrapGuard);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Android源码里面是这样写的,用位移的效率要高一些,我仅仅是根据理论知识推测效率要比判断要高,没有进行过对比。

static inline int16_t clamp16(int32_t sample)
{
    if ((sample>>15) ^ (sample>>31))
        sample = 0x7FFF ^ (sample>>31);
    return sample;
}


ffmpeg一个非常强大的多媒体处理工具,通过一系列的命令可以完成各种音视频处理任务。以下是对ffmpeg命令的详解: 1. 合成视频:可以将多个图片序列帧和音频文件合成为视频文件。例如,可以使用以下命令将darkdoor.[001-100].jpg序列帧和001.mp3音频文件合成为视频文件darkdoor.avi: ffmpeg -i 001.mp3 -i darkdoor.%d.jpg -s 1024x768 -author skypp -vcodec mpeg4 darkdoor.avi 2. 导出视频:可以将视频文件导出为其他格式,如mov格式。例如,可以使用以下命令将darkdoor.avi导出为darkdoor.mov: ffmpeg -i darkdoor.avi darkdoor.mov 3. 导出图片序列帧:可以将视频文件导出为一系列的图片序列帧。例如,可以使用以下命令将bc-cinematic-en.avi导出为example.%d.jpg序列帧: ffmpeg -i bc-cinematic-en.avi example.%d.jpg 4. 安装ffmpeg:在Debian系统下,可以使用以下命令安装ffmpeg: apt-get install ffmpeg 综上所述,ffmpeg一个功能强大的多媒体处理工具,可以完成音视频剪切、转码、滤镜、拼接、混音、截图等任务。详细的使用方法可以参考FFmpeg官方文档[4]。 引用: ffmpeg命令详解 ffmpeg非常强大,轻松几条命令就可以完成你的工作 在cmd中先将目录切换到ffmpeg.exe对应的文件目录 FFmpeg多媒体库支持的命令行调用分为三个模块:ffmpeg、ffprobe、ffplay。其中ffmpeg命令行常用于音视频剪切、转码、滤镜、拼接、混音、截图等;ffprobe用于检测多媒体流格式;ffplay用于播放视频。详情可查阅FFmpeg官方文档:ffmpeg Documentation。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值