AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1692801
Accepted
Gerhard Schreurs
Gerhard Schreurs
Asked: 2021-12-14 03:50:48 +0800 CST2021-12-14 03:50:48 +0800 CST 2021-12-14 03:50:48 +0800 CST

ffmpeg:使用 Microsoft PCM 导出为 24 位波形,不可扩展(使用 Lavf58.76.100)

  • 772

我注意到,当我使用 FFMPEG 将 mod 导出为 24 位或更高位的波形时,FFMPEG 决定使用可扩展编码而不是常规 PCM 编码并使用“Lavf58.76.100”,不管是什么。我使用 exiftool 检查导出的 wav,结果如下:

---- File ----
File Type                       : WAV
File Type Extension             : wav
MIME Type                       : audio/x-wav
---- RIFF ----
Encoding                        : Extensible
Num Channels                    : 2
Sample Rate                     : 48000
Avg Bytes Per Sec               : 288000
Bits Per Sample                 : 24
Software                        : Lavf58.76.100

问题是,许多程序不理解这种可扩展的 wav 格式。有没有办法告诉 FFMPEG 改用常规 PCM?我注意到其他程序(例如低音库)可以使用常规 PCM 编码导出为 24 位 wav。

这是我正在使用的命令:

ffmpeg -y -loglevel error -f libopenmpt -i c:\temp\sometrack.IT -map_metadata -1 -c:a pcm_s24le c:\temp\sometrack.wav

编辑

当我写这个问题时,我有点沮丧并且缺乏知识。现在,一切都非常清楚了;位深度高于 16 位的 wave 文件,应具有 WAVE_FORMAT_EXTENSIBLE 标记(这是有道理的,请参阅答案)。除了 FFmpeg,我用来将 mod 文件渲染为 wave 的软件不遵守这条规则。谢谢 Tom Yan 的澄清。

export ffmpeg
  • 1 1 个回答
  • 310 Views

1 个回答

  • Voted
  1. Best Answer
    Tom Yan
    2021-12-14T08:30:04+08:002021-12-14T08:30:04+08:00

    (并非我的所有评论都是准确/正确的,因此如果您有兴趣,请参阅以下内容。)

    从理论上讲,PCMWAVEFORMAT可用于比特深度高于 16 的音频。标头结构不构成任何限制,阻止其自身支持此类音频。

    但是,ffmpeg 没有为这种音频编写这种格式的 WAVE 标头显然有几个原因。

    一方面,该格式已被 , 取代WAVEFORMATEX,并且根据文档:

    ...
    
    wBitsPerSample
    
    ... If wFormatTag is WAVE_FORMAT_PCM, then wBitsPerSample should be equal to
    8 or 16. ...
    
    ...
    

    除上述要求外,没有为比特深度高于 16 的 PCM 音频定义的wFormatTag值。WAVE_FORMAT_EXTENSIBLE

    中定义的“扩展”是否WAVEFORMATEXTENSIBLE可以在 is 时wFormatTag省略WAVE_FORMAT_EXTENSIBLE并不完全清楚。在WAVEFORMATEX中,指出:

    ...
    
    wFormatTag
    
    
    ... When this structure is included in a WAVEFORMATEXTENSIBLE structure,
    this value must be WAVE_FORMAT_EXTENSIBLE. ...
    
    ...
    

    有了这样的声明,可能没有人会/不应该假设它是被允许的。

    如果您仔细阅读WAVEFORMATEX,WAVEFORMATEXTENSIBLE您会注意到后者存在的真正原因(就位深度而言)是,它允许前者存储 8 的倍数容器大小,而“真实”样本大小存储在后者中定义的扩展之一。例如,对于某些(讨厌的)20 位 PCM 流,分别为 24 和 20。

    不过,wav据我所知,ffmpeg 的多路复用器不(至少不正确)支持刚才提到的古怪案例。0(我认为,如果这样的流没有被拒绝,这两个字段的值都将被写入。)

    如果您确实需要 ffmpeg 以PCMWAVEFORMAT24 位音频的格式编写标头,您可以考虑使用以下补丁构建它:

    diff --git a/libavformat/riff.h b/libavformat/riff.h
    index 85d6786663..5794857f53 100644
    --- a/libavformat/riff.h
    +++ b/libavformat/riff.h
    @@ -57,6 +57,11 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, int for_asf, int
      */
     #define FF_PUT_WAV_HEADER_SKIP_CHANNELMASK      0x00000002
     
    +/**
    + * Tell ff_put_wav_header() not to write WAVEFORMATEXTENSIBLE extensions if possible.
    + */
    +#define FF_PUT_WAV_HEADER_FORCE_PCMWAVEFORMAT      0x00000004
    +
     /**
      * Write WAVEFORMAT header structure.
      *
    diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
    index ffccfa3d48..4dc8ca6e0f 100644
    --- a/libavformat/riffenc.c
    +++ b/libavformat/riffenc.c
    @@ -80,9 +80,9 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
         waveformatextensible = (par->channels > 2 && par->channel_layout) ||
                                par->channels == 1 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_MONO ||
                                par->channels == 2 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_STEREO ||
    -                           par->sample_rate > 48000 ||
                                par->codec_id == AV_CODEC_ID_EAC3 ||
    -                           av_get_bits_per_sample(par->codec_id) > 16;
    +                           ((par->sample_rate > 48000 || av_get_bits_per_sample(par->codec_id) > 16) &&
    +                            !(flags & FF_PUT_WAV_HEADER_FORCE_PCMWAVEFORMAT));
     
         if (waveformatextensible)
             avio_wl16(pb, 0xfffe);
    diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c
    index 2317700be1..bd41d6eeb3 100644
    --- a/libavformat/wavenc.c
    +++ b/libavformat/wavenc.c
    @@ -83,6 +83,7 @@ typedef struct WAVMuxContext {
         int peak_block_pos;
         int peak_ppv;
         int peak_bps;
    +    int extensible;
     } WAVMuxContext;
     
     #if CONFIG_WAV_MUXER
    @@ -324,9 +325,10 @@ static int wav_write_header(AVFormatContext *s)
         }
     
         if (wav->write_peak != PEAK_ONLY) {
    +        int flags = !wav->extensible ? FF_PUT_WAV_HEADER_FORCE_PCMWAVEFORMAT : 0;
             /* format header */
             fmt = ff_start_tag(pb, "fmt ");
    -        if (ff_put_wav_header(s, pb, s->streams[0]->codecpar, 0) < 0) {
    +        if (ff_put_wav_header(s, pb, s->streams[0]->codecpar, flags) < 0) {
                 av_log(s, AV_LOG_ERROR, "Codec %s not supported in WAVE format\n",
                        avcodec_get_name(s->streams[0]->codecpar->codec_id));
                 return AVERROR(ENOSYS);
    @@ -494,6 +496,7 @@ static const AVOption options[] = {
         { "peak_block_size", "Number of audio samples used to generate each peak frame.",   OFFSET(peak_block_size), AV_OPT_TYPE_INT, { .i64 = 256 }, 0, 65536, ENC },
         { "peak_format",     "The format of the peak envelope data (1: uint8, 2: uint16).", OFFSET(peak_format), AV_OPT_TYPE_INT,     { .i64 = PEAK_FORMAT_UINT16 }, PEAK_FORMAT_UINT8, PEAK_FORMAT_UINT16, ENC },
         { "peak_ppv",        "Number of peak points per peak value (1 or 2).",              OFFSET(peak_ppv), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, 2, ENC },
    +    { "extensible",      "Write WAVEFORMATEXTENSIBLE extensions.",                      OFFSET(extensible), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC },
         { NULL },
     };
     
    

    然后通过-extensible 0在输出文件路径/名称之前添加,您应该能够获得所谓的“常规”24 位 WAVE 文件。

    • 0

相关问题

  • 最低比特率 ffmpeg 输出的编解码器和设置

  • 如何用ffmpeg 2.0.2保存TS视频流?

  • 快速提取 I 帧到图像

  • 如何导入螳螂项目?

  • 压缩视频可以解码回未压缩的原始格式吗?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何减少“vmmem”进程的消耗?

    • 11 个回答
  • Marko Smith

    从 Microsoft Stream 下载视频

    • 4 个回答
  • Marko Smith

    Google Chrome DevTools 无法解析 SourceMap:chrome-extension

    • 6 个回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Martin Hope
    Saaru Lindestøkke 为什么使用 Python 的 tar 库时 tar.xz 文件比 macOS tar 小 15 倍? 2021-03-14 09:37:48 +0800 CST
  • Martin Hope
    CiaranWelsh 如何减少“vmmem”进程的消耗? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Windows 10 搜索未加载,显示空白窗口 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 为什么通过电缆(同轴电缆)的千兆位/秒 Internet 连接不能像光纤一样提供对称速度? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve