[PATCH] avformat/wavenc: use RF64 when needed
Currently if you encode a large wav, ffmpeg will hint after the fact that the resultant file is corrupted, because traditional wav cannot handle lengths greater than 32-bits. This isn't very useful; nobody benefits from getting garbage files. You can manually work around this by adding `-rf64 always`, which most players have support for. Most people don't remember to do this until after the fact when their file is corrupted, or they don't figure it out at all and wind up using the w64 container instead. And so that's what `-rf64 auto` is for. It uses the larger format when needed, and if not, uses the traditional wav that is probably more compatible. The result of using `-rf64 auto` is that you can add it to every command line -- and should add it to every command line -- to get either a normal small file, or a non-corrupt large file. This is a very sensible default to have on, rather than just producing corrupt files and having users scrambling for solutions, and then having to do a potentially expensive reencode after. With `-rf64 auto` on by default, the user always gets a readable good file. And for users who sometimes want corrupt files, there still exists `-rf64 never` that can be enabled. --- libavformat/wavenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index a515f4e2a2..835a2157bc 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -487,7 +487,7 @@ static const AVOption options[] = { { "off", "Do not write peak chunk.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_OFF }, 0, 0, ENC, .unit = "peak" }, { "on", "Append peak chunk after wav data.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_ON }, 0, 0, ENC, .unit = "peak" }, { "only", "Write only peak chunk, omit wav data.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_ONLY }, 0, 0, ENC, .unit = "peak" }, - { "rf64", "Use RF64 header rather than RIFF for large files.", OFFSET(rf64), AV_OPT_TYPE_INT, { .i64 = RF64_NEVER },-1, 1, ENC, .unit = "rf64" }, + { "rf64", "Use RF64 header rather than RIFF for large files.", OFFSET(rf64), AV_OPT_TYPE_INT, { .i64 = RF64_AUTO },-1, 1, ENC, .unit = "rf64" }, { "auto", "Write RF64 header if file grows large enough.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_AUTO }, 0, 0, ENC, .unit = "rf64" }, { "always", "Always write RF64 header regardless of file size.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_ALWAYS }, 0, 0, ENC, .unit = "rf64" }, { "never", "Never write RF64 header regardless of file size.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_NEVER }, 0, 0, ENC, .unit = "rf64" }, -- 2.52.0
Hi Jason On Sat, Dec 20, 2025 at 10:28:39PM +0100, Jason A. Donenfeld via ffmpeg-devel wrote:
Currently if you encode a large wav, ffmpeg will hint after the fact that the resultant file is corrupted, because traditional wav cannot handle lengths greater than 32-bits. This isn't very useful; nobody benefits from getting garbage files.
You can manually work around this by adding `-rf64 always`, which most players have support for. Most people don't remember to do this until after the fact when their file is corrupted, or they don't figure it out at all and wind up using the w64 container instead.
And so that's what `-rf64 auto` is for. It uses the larger format when needed, and if not, uses the traditional wav that is probably more compatible. The result of using `-rf64 auto` is that you can add it to every command line -- and should add it to every command line -- to get either a normal small file, or a non-corrupt large file.
This is a very sensible default to have on, rather than just producing corrupt files and having users scrambling for solutions, and then having to do a potentially expensive reencode after. With `-rf64 auto` on by default, the user always gets a readable good file. And for users who sometimes want corrupt files, there still exists `-rf64 never` that can be enabled. --- libavformat/wavenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index a515f4e2a2..835a2157bc 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -487,7 +487,7 @@ static const AVOption options[] = { { "off", "Do not write peak chunk.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_OFF }, 0, 0, ENC, .unit = "peak" }, { "on", "Append peak chunk after wav data.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_ON }, 0, 0, ENC, .unit = "peak" }, { "only", "Write only peak chunk, omit wav data.", 0, AV_OPT_TYPE_CONST, { .i64 = PEAK_ONLY }, 0, 0, ENC, .unit = "peak" }, - { "rf64", "Use RF64 header rather than RIFF for large files.", OFFSET(rf64), AV_OPT_TYPE_INT, { .i64 = RF64_NEVER },-1, 1, ENC, .unit = "rf64" }, + { "rf64", "Use RF64 header rather than RIFF for large files.", OFFSET(rf64), AV_OPT_TYPE_INT, { .i64 = RF64_AUTO },-1, 1, ENC, .unit = "rf64" }, { "auto", "Write RF64 header if file grows large enough.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_AUTO }, 0, 0, ENC, .unit = "rf64" }, { "always", "Always write RF64 header regardless of file size.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_ALWAYS }, 0, 0, ENC, .unit = "rf64" }, { "never", "Never write RF64 header regardless of file size.", 0, AV_OPT_TYPE_CONST, { .i64 = RF64_NEVER }, 0, 0, ENC, .unit = "rf64" },
breaks fate: --- - 2025-12-21 04:04:18.901071242 +0100 +++ tests/data/fate/filter-channelmap-one-str 2025-12-21 04:04:18.898363748 +0100 @@ -1 +1 @@ -e18791f65ce5861e130b2c3e472ab90a +8f8a664b694f18e1e9ae1b9ccfa6f30c Test filter-channelmap-one-str failed. Look at tests/data/fate/filter-channelmap-one-str.err for details. make: *** [tests/Makefile:323: fate-filter-channelmap-one-str] Error 1 if this change is intended, then update the fate tests and explain in the commit message why they change thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB The real ebay dictionary, page 1 "Used only once" - "Some unspecified defect prevented a second use" "In good condition" - "Can be repaird by experienced expert" "As is" - "You wouldnt want it even if you were payed for it, if you knew ..."
On Sat, Dec 20, 2025 at 1:29 PM Jason A. Donenfeld via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> wrote:
Currently if you encode a large wav, ffmpeg will hint after the fact that the resultant file is corrupted, because traditional wav cannot handle lengths greater than 32-bits. This isn't very useful; nobody benefits from getting garbage files.
You can manually work around this by adding `-rf64 always`, which most players have support for. Most people don't remember to do this until after the fact when their file is corrupted, or they don't figure it out at all and wind up using the w64 container instead.
And so that's what `-rf64 auto` is for. It uses the larger format when needed, and if not, uses the traditional wav that is probably more compatible. The result of using `-rf64 auto` is that you can add it to every command line -- and should add it to every command line -- to get either a normal small file, or a non-corrupt large file.
This is a very sensible default to have on, rather than just producing corrupt files and having users scrambling for solutions, and then having to do a potentially expensive reencode after. With `-rf64 auto` on by default, the user always gets a readable good file. And for users who sometimes want corrupt files, there still exists `-rf64 never` that can be enabled. ---
Hi, I am not opposed to changing the default, but I recall there were some reports of problems[1] when ffmpeg began to stray from the "classic" WAV file layout. The `-rf64 auto` option adds an extra junk chunk near the beginning of the file, before the "fmt " chunk, to reserve space for the extended header if needed. While most WAV-consuming software will ignore unknown chunk types gracefully, some tools assume a fixed header layout and will produce garbage audio data when reading a file with extra header chunks or with "fmt " not being the first chunk (at least this is my vague recollection when looking into this some time ago). That said, these issues happened years ago, and perhaps most software is fixed by now (and arguably, any software that does not handle these files is buggy); on the other hand, attempting to put more than 4 GB of audio data in a WAV file is probably pretty uncommon, and there are other formats that can handle large audio data if the specific format doesn't have to be WAV. (WAV probably has better name recognition, though.) Thanks, -- Daniel [1]: A related mailing list thread from 2013, which unfortunately doesn't name the specific broken software: https://ffmpeg.org/pipermail/ffmpeg-devel/2013-April/thread.html#142560
Hi Daniel, On Tue, Dec 30, 2025 at 5:50 AM Daniel Verkamp <daniel@drv.nu> wrote:
I am not opposed to changing the default, but I recall there were some reports of problems[1] when ffmpeg began to stray from the "classic" WAV file layout.
The `-rf64 auto` option adds an extra junk chunk near the beginning of the file, before the "fmt " chunk, to reserve space for the extended header if needed.
This is not what `-rf64 auto` does, and I think your reply might be skipping an important step. Namely, `-rf64 auto` only goes into riff64 mode when there's no way to construct a valid wav32 to hold the data. So, here are the effects of the different settings: - `-rf64 no`: makes a valid wav file, unless it's too long, and then it produces a corrupt file that can't be played anywhere. *This corruption-producing behavior is the current bad default.* - `-rf64 yes`: always makes a riff64 file, which these days generally has universal support, but ys, at some point long long ago, there were some old players that didn't know about it. *This is _not_ the option I'm proposing we make default.* - `-rf64 auto`: make a valid wav file if it can do so, but then, if it can't, rather than producing a corrupt output file, make a riff64 file, so that it'll still be playable in 99% of the places. *This is what I'm proposing we turn on by default." So, as you can see, `-rf64 auto` is strictly better than the status quo, offering no drawback. It produces a riff64 file only in the case when ffmpeg would _otherwise generate a corrupt unplayable file_. Jason
On Tue, Dec 30, 2025 at 3:17 AM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
Hi Daniel,
On Tue, Dec 30, 2025 at 5:50 AM Daniel Verkamp <daniel@drv.nu> wrote:
I am not opposed to changing the default, but I recall there were some reports of problems[1] when ffmpeg began to stray from the "classic" WAV file layout.
The `-rf64 auto` option adds an extra junk chunk near the beginning of the file, before the "fmt " chunk, to reserve space for the extended header if needed.
This is not what `-rf64 auto` does, and I think your reply might be skipping an important step. Namely, `-rf64 auto` only goes into riff64 mode when there's no way to construct a valid wav32 to hold the data.
Right, the RIFF to RF64 conversion and creation of the ds64 chunk only happen as needed in `-rf64 auto` mode. However, it still changes the file layout even when the RF64 conversion doesn't trigger (see below). I did actually intend to make `-rf64 auto` the default when the RF64 support was originally added, but it got merged with `-rf64 never` as default instead (https://ffmpeg.org/pipermail/ffmpeg-devel/2013-February/138901.html) and I never got around to changing it. I think it's probably reasonable to change it now, but I wanted to add some minor clarifications below about the potential compatibility issue I was discussing.
So, here are the effects of the different settings:
- `-rf64 no`: makes a valid wav file, unless it's too long, and then it produces a corrupt file that can't be played anywhere. *This corruption-producing behavior is the current bad default.*
It is actually readable in some software (including ffmpeg itself when using `-ignore_length 1`, although this is not the default), so the data is not truly lost, but I agree it is generally better to do the right thing by default, assuming it doesn't cause other problems.
- `-rf64 yes`: always makes a riff64 file, which these days generally has universal support, but ys, at some point long long ago, there were some old players that didn't know about it. *This is _not_ the option I'm proposing we make default.*
Right, and I don't think it would ever make sense to make this the default for the WAV muxer, since it would not produce actual WAV files matching the Microsoft spec anymore at that point. This option only really exists to make testing RF64 support easier (without needing a gigantic test file).
- `-rf64 auto`: make a valid wav file if it can do so, but then, if it can't, rather than producing a corrupt output file, make a riff64 file, so that it'll still be playable in 99% of the places. *This is what I'm proposing we turn on by default."
So, as you can see, `-rf64 auto` is strictly better than the status quo, offering no drawback. It produces a riff64 file only in the case when ffmpeg would _otherwise generate a corrupt unplayable file_.
The compatibility issue I mentioned is not related to the RIFF versus RF64 format change (which only triggers for large files, as you mentioned); it's that adding the extra reserved space for the potentially-needed RF64 header extension, which always happens in `-rf64 auto` mode even if the file ends up being a normal WAV and not RF64, causes the headers prior to the audio data to not be the exact 44-byte size expected by (buggy) software. In addition to the ffmpeg mailing list thread I mentioned before, there's another mention of this in https://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html - "Some programs (naively) assume that for PCM data, the preamble in the file header is exactly 44 bytes long" - so presumably this shortcut has been independently reinvented more than once. That said, I think it's fair to say that switching to `-rf64 auto` by default won't cause further compatibility problems due to breaking the 44-byte header assumption, because current ffmpeg already doesn't generate such files (although it did at some point in the distant past). WAV files generated by the ffmpeg CLI now have a "ISFT" chunk containing the libavformat version, so the header won't be the magic 44-byte size regardless of whether the extra reserved-for-ds64 padding is added. In other words, any supposed compatibility improvements we'd get by trying to stick with the expected "classic" layout were already lost when the encoder metadata was added; I should have peeked in a hex editor rather than relying on my recollection. :) So in summary, I think switching to `-rf64 auto` by default is fine. It just needs a FATE reference update as Michael mentioned; `make fate-rsync` to get the samples and then `make fate GEN=1` should take care of most of the necessary updates. Thanks, -- Daniel
Hi Daniel, On Wed, Dec 31, 2025 at 8:43 AM Daniel Verkamp <daniel@drv.nu> wrote:
The compatibility issue I mentioned is not related to the RIFF versus RF64 format change (which only triggers for large files, as you mentioned); it's that adding the extra reserved space for the potentially-needed RF64 header extension, which always happens in `-rf64 auto` mode even if the file ends up being a normal WAV and not RF64, causes the headers prior to the audio data to not be the exact 44-byte size expected by (buggy) software.
Ahh, thank you for the explanation. This also explains what Michael found in his failed test.
So in summary, I think switching to `-rf64 auto` by default is fine. It just needs a FATE reference update as Michael mentioned; `make fate-rsync` to get the samples and then `make fate GEN=1` should take care of most of the necessary updates.
Will do. Thanks for laying this out for me. v2 on its way. Jason
Hi Daniel On Tue, Dec 30, 2025 at 11:43:17PM -0800, Daniel Verkamp via ffmpeg-devel wrote:
On Tue, Dec 30, 2025 at 3:17 AM Jason A. Donenfeld <Jason@zx2c4.com> wrote: [...] That said, I think it's fair to say that switching to `-rf64 auto` by default won't cause further compatibility problems due to breaking the 44-byte header assumption, because current ffmpeg already doesn't generate such files (although it did at some point in the distant past). WAV files generated by the ffmpeg CLI now have a "ISFT" chunk containing the libavformat version, so the header won't be the magic 44-byte size regardless of whether the extra reserved-for-ds64 padding is added. In other words, any supposed compatibility improvements we'd get by trying to stick with the expected "classic" layout were already lost when the encoder metadata was added; I should have peeked in a hex editor rather than relying on my recollection. :)
Someone should add a classic44_wav mode. So we cab generate files for these ancient devices that expect that thx [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Arguing that you don’t care about the right to privacy because you have nothing to hide is no different than saying you don’t care about free speech because you have nothing to say - Edward Snowden
participants (3)
-
Daniel Verkamp -
Jason A. Donenfeld -
Michael Niedermayer