【问题标题】:How to convert stereo sound to mono with FFmpeg?如何使用 FFmpeg 将立体声转换为单声道?
【发布时间】:2017-01-22 02:16:27
【问题描述】:

我将 FFmpeg 库用于个人项目,我需要关于一件事的帮助。我有一个立体声音乐文件,我想将此立体声转换为单声道?这个库可以吗?里面有没有做这项工作的功能?我的项目是 C/C++。

我在 FFmpeg 网站和这个论坛上搜索了 Doxygen 文档,但没有找到有趣的东西。

感谢阅读!

【问题讨论】:

  • 我记得没有函数,但是您可以通过一起计算两个流来轻松地自己转换它。
  • 你有什么代码可以举个例子吗?

标签: c++ function audio ffmpeg


【解决方案1】:

你可以只使用 ffmpeg。直接命令是为了这个目的而存在的-

ffmpeg -i stereo.flac -ac 1 mono.flac

会将您的立体声文件转换为单声道。更多详情,你可以看看这个页面-

https://trac.ffmpeg.org/wiki/AudioChannelManipulation

【讨论】:

  • 谢谢,帮了我很多忙!顺便说一句,如果其他人需要像我一样连续转换大量文件:find . -name '*.mp4' -exec ./convert.sh {} \;
  • 然后,在convert.sh 文件中:
  • ffmpeg -i $1 -ac 1 $1.mono.mp4
  • @MarcoArruda 您可以通过直接调用ffmpeg 来跳过convert.sh 文件:find . -name '*.mp4' -exec ffmpeg -i '{}' -ac 1 '{}.mono.mp4' \;
  • 这会使响亮的部分剪辑很多。有没有办法在不剪裁的情况下将其展平
【解决方案2】:

使用 libswresample 中的 swr_convert 在格式之间进行转换。比如:

#include "libswresample/swresample.h"

au_convert_ctx = swr_alloc();

out_channel_layout = AV_CH_LAYOUT_MONO;
out_sample_fmt = AV_SAMPLE_FMT_S16;
out_sample_rate = 44100;
out_channels = av_get_channel_layout_nb_channels(out_channel_layout);

in_sample_fmt = pCodecCtx->sample_fmt;
in_channel_layout=av_get_default_channel_layout(pCodecCtx->channels);

au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,out_channel_layout, out_sample_fmt, out_sample_rate,
            in_channel_layout, in_sample_fmt, pCodecCtx->sample_rate, 0, NULL);
swr_init(au_convert_ctx);
//Generate your frame of original audio, then use swr_convert to convert to mono,
//converted number of samples will now be in out_buffer.
int converted = swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)&pFrame->data , pFrame->nb_samples);
//...
swr_free(&au_convert_ctx);

让你开始。这会将原始格式恰好转换为 44100 kHz 单声道。您也可以使用pCodecCtx->sample_rate 作为输出采样率。

这是最灵活、最简单的解决方案。

【讨论】:

    【解决方案3】:

    正如我在评论中提到的,您可以自己重新采样。这取决于您已经拥有什么以及您使用什么格式。我不能给你立即工作的代码,但给你一个例子(伪/真实代码混合)。

    在您对帧进行编码并完成您必须做的事情后,您的数据缓冲区将被音频填充。现在这取决于您的格式(请参阅here)以及您拥有多少个频道。假设它是签名的 16 位立体声,而不是您的缓冲区:

    +-----+-----+-----+-----+-----+
    | LS1 | RS1 | LS2 | RS2 | ... |
    +-----+-----+-----+-----+-----+
    // LS = LEFT SAMPLE 16 Bit
    // RS = RIGHT SAMPLE 16 Bit
    

    现在遍历缓冲区并一起计算左右样本。

    for(int i=0; i<sample_size; i+=2) {
        auto r = (static_cast<int32_t>(buffer[i]) + buffer[i+1]) / 2;
        buffer[i] = buffer[i+1] = r;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多