FFmpeg 中编译和使用 soxr 重采样引擎

1. soxr vs swr 重采样器

FFmpeg 的 libswresample 默认使用内置的 SWR 引擎进行音频重采样。此外还支持通过编译选项 --enable-libsoxr 集成 SoX Resampler (soxr) 作为替代引擎。

特性 内置 SWR soxr
重采样质量 良好,适合大多数场景 更高,适合对音频质量敏感的场景
性能 较快 略慢(高质量滤波器更长)
编译依赖 无,FFmpeg 自带 需要额外编译 libsoxr

适用场景:对重采样质量有较高要求的音频处理流程,例如专业音频制作、科学信号处理、需要与其他高质量重采样库对齐结果的场景等。

2. 四端编译 soxr

从 SourceForge 下载 soxr 0.1.3 源码,使用 CMake 编译静态库。

macOS (Fat 库,支持 arm64 + x86_64)

bash 复制代码
for ARCH in $ARCHS; do
    echo "building soxr for $ARCH..."
    BUILD_DIR="$SHELL_DIR/soxr-build-$ARCH"
    mkdir -p "$BUILD_DIR"
    cd "$BUILD_DIR"
    cmake "$SOXR_SRC" -DCMAKE_OSX_ARCHITECTURES="$ARCH" \
        -DCMAKE_INSTALL_PREFIX="$THIN_SOXR/$ARCH" \
        -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release \
        || exit 1
    cmake --build . -j8 || exit 1
    cmake --install . || exit 1
    cd -
    rm -rf "$BUILD_DIR"
done
# 合并 Fat 库
lipo -create "$THIN_SOXR/arm64/lib/libsoxr.a" "$THIN_SOXR/x86_64/lib/libsoxr.a" \
     -output "$FAT_SOXR/lib/libsoxr.a"

iOS

bash 复制代码
if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]; then
    SOXR_SDK="iphonesimulator"
else
    SOXR_SDK="iphoneos"
fi
SOXR_SYSROOT=$(xcrun --sdk $SOXR_SDK --show-sdk-path)

cmake "$SOXR_SRC" \
    -DCMAKE_OSX_ARCHITECTURES="$ARCH" \
    -DCMAKE_OSX_SYSROOT="$SOXR_SYSROOT" \
    -DCMAKE_OSX_DEPLOYMENT_TARGET="$DEPLOYMENT_TARGET" \
    -DCMAKE_INSTALL_PREFIX="$THIN_SOXR/$ARCH" \
    -DBUILD_SHARED_LIBS=OFF \
    -DBUILD_TESTS=OFF \
    -DCMAKE_BUILD_TYPE=Release

Android

bash 复制代码
cmake "$SOXR_SRC" \
    -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} \
    -DANDROID_ABI=${ANDROID_ABI} \
    -DANDROID_PLATFORM=${ANDROID_PLATFORM} \
    -DCMAKE_INSTALL_PREFIX=${SOXR_INSTALL_DIR} \
    -DBUILD_SHARED_LIBS=OFF \
    -DCMAKE_BUILD_TYPE=Release \
    -DWITH_OPENMP=OFF \
    -DBUILD_TESTS=OFF \
    -DBUILD_EXAMPLES=OFF

Windows

bash 复制代码
cmake -G "Ninja" -S "${SOXR_SRC}" -B "${basepath}/soxr-build" \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_SHARED_LIBS=OFF \
    -DBUILD_TESTS=OFF \
    -DBUILD_SHARED_RUNTIME=OFF \
    -DCMAKE_INSTALL_PREFIX=${basepath}/soxr_install

Windows 注意事项 :soxr 的 CMakeLists.txt 最低版本要求为 3.1,不支持 CMAKE_MSVC_RUNTIME_LIBRARY。MT/MD 的切换只能通过 soxr 自身提供的 BUILD_SHARED_RUNTIME 选项控制(OFF = MT,ON = MD)。

编译完成后,在 FFmpeg 的 configure 中添加:

bash 复制代码
--enable-libsoxr --extra-cflags="-I${SOXR_INSTALL}/include" --extra-ldflags="-L${SOXR_INSTALL}/lib"

静态库打包 :如果 soxr 和 FFmpeg 都编译为静态库,需要将 libsoxr.a 的目标文件合并到 libswresample.a 中,否则下游链接时会出现未定义符号错误。

3. 使用 soxr 引擎

在创建 SwrContext 后、swr_init 之前(或首次 swr_convert_frame 前),通过 AVOption 设置引擎及参数:

cpp 复制代码
SwrContext* swr = swr_alloc();
av_opt_set_int(swr, "resampler", SWR_ENGINE_SOXR, 0);     // 切换到 soxr 引擎
av_opt_set_double(swr, "precision", 33.0, 0);              // 重采样精度(bit)
av_opt_set_double(swr, "cutoff", 0.84, 0);                 // 通带截止频率

以上参数配置下的重采样效果与 Python resampy 库的默认重采样结果一致。

可以通过运行时检测当前 FFmpeg 是否编译了 soxr 支持:

cpp 复制代码
bool isSoxrSupported() {
    return strstr(swresample_configuration(), "enable-libsoxr") != nullptr;
}

4. 注意事项:soxr flush 阶段的已知问题

使用 swr_convert_frame + SWR_ENGINE_SOXR 复用输出 AVFrame 时,如果 output buffer 容量不足,SwrContext 内部会累积未消耗的输入数据(in_buffer)。在最后 flush 阶段,FFmpeg 的 soxr 集成层(soxr_resample.c)会先向 soxr 发送输入终结信号,再尝试处理 in_buffer 残留数据,导致 soxr 在终结状态下收到输入而崩溃。内置 SWR 引擎不受此影响。

规避方法 :每次 swr_convert_frame 调用前,通过 swr_get_out_samples 获取预期输出量,确保 output buffer 容量足够,使 in_buffer 始终为空:

cpp 复制代码
if (swr_is_initialized(swrCtx)) {
    int expected = swr_get_out_samples(swrCtx, in_frame->nb_samples);  // flush 时传 0
    reserveFrame(expected);  // 仅在 expected > capacity 时才重新分配
}

该问题属于 FFmpeg soxr_resample.c 的集成缺陷,后续计划尝试从 FFmpeg 源码层面修复。

相关推荐
TechVoyager_82461 天前
多形态输入与12 通道音频:IT6615 这颗 HDMI 发射器的接口宽度
音视频·音频芯片·芯片选型·视频发射
Raymond16881 天前
AI配音工具长文本合成架构技术解析:全局音色锚定与声学状态跟踪
人工智能·架构·实时互动·视觉检测·音视频·语音识别
hflmwl81 天前
Wise Data Recovery找回误删的文档照片音乐和视频
音视频·datarecovery·找回误删的文档照片音乐和视频·找回误删的文档照片音乐视频
技灵AI1 天前
AI 视频转场提示词怎么写?让前后画面衔接更自然
人工智能·prompt·aigc·音视频
youandyouyou1 天前
跨区培训的屏幕共享怎么做才稳?同屏同步与弱网优化实践
音视频·网络通信
开开心心就好1 天前
课堂随机点名工具,绿色版免安装双击即用
java·服务器·前端·ffmpeg·音视频·perl·symfony
美狐美颜SDK开放平台1 天前
直播APP集成美颜SDK,如何梳理第三方组件的数据权限?
开发语言·人工智能·深度学习·音视频·第三方美颜sdk
小鹿软件办公1 天前
不依赖 FFmpeg 也能录屏?ShareX 22 新增录屏等十余款新工具
ffmpeg·sharex·免费录屏工具
l14372332671 天前
批量视频硬字幕擦除多少钱?影响报价的关键因素全解析
音视频
重生六道1 天前
B站视频时长统计:一段JS脚本搞定分P/合集总时长(附倍速计算)
开发语言·javascript·音视频