Opened 15 months ago
#11559 new defect
Vorbis Comment fields renamed
| Reported by: | Timon Martins | Owned by: | |
|---|---|---|---|
| Priority: | normal | Component: | avformat |
| Version: | 7.1 | Keywords: | ogg opus flac |
| Cc: | Blocked By: | ||
| Blocking: | Reproduced by developer: | no | |
| Analyzed by developer: | no |
Description
Summary of the bug:
When writing metadata to an opus file and afterwards reading that same metadata, the field names do not match.
Note how it says description in the output of the second command, but comment in the output of the third.
How to reproduce:
$ ffprobe -show_entries stream_tags little-metadata.opus 2> /dev/null
[STREAM]
TAG:language=eng
TAG:encoder=Lavf61.7.100
[/STREAM]
$ ffmpeg -i little-metadata.opus -map 0 -c copy -metadata "description=A good description" more-metadata.opus
ffmpeg version 7.1.1 Copyright (c) 2000-2025 the FFmpeg developers
built with Apple clang version 15.0.0 (clang-1500.1.0.2.5)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.1.1_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
libavutil 59. 39.100 / 59. 39.100
libavcodec 61. 19.101 / 61. 19.101
libavformat 61. 7.100 / 61. 7.100
libavdevice 61. 3.100 / 61. 3.100
libavfilter 10. 4.100 / 10. 4.100
libswscale 8. 3.100 / 8. 3.100
libswresample 5. 3.100 / 5. 3.100
libpostproc 58. 3.100 / 58. 3.100
Input #0, ogg, from 'little-metadata.opus':
Duration: 00:03:31.71, start: 0.007500, bitrate: 119 kb/s
Stream #0:0(eng): Audio: opus, 48000 Hz, stereo, fltp
Metadata:
encoder : Lavf61.7.100
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Output #0, opus, to 'more-metadata.opus':
Metadata:
description : A good description
encoder : Lavf61.7.100
Stream #0:0(eng): Audio: opus, 48000 Hz, stereo, fltp
Metadata:
encoder : Lavf61.7.100
description : A good description
Press [q] to stop, [?] for help
[out#0/opus @ 0x600001c9c240] video:0KiB audio:3068KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.833101%
size= 3093KiB time=00:03:31.69 bitrate= 119.7kbits/s speed=7.67e+03x
$ ffprobe -show_entries stream_tags more-metadata.opus 2> /dev/null
[STREAM]
TAG:language=eng
TAG:encoder=Lavf61.7.100
TAG:comment=A good description
[/STREAM]
File info:
$ ffmpeg -v 9 -loglevel 99 -i little-metadata.opus
ffmpeg version 7.1.1 Copyright (c) 2000-2025 the FFmpeg developers
built with Apple clang version 15.0.0 (clang-1500.1.0.2.5)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.1.1_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
libavutil 59. 39.100 / 59. 39.100
libavcodec 61. 19.101 / 61. 19.101
libavformat 61. 7.100 / 61. 7.100
libavdevice 61. 3.100 / 61. 3.100
libavfilter 10. 4.100 / 10. 4.100
libswscale 8. 3.100 / 8. 3.100
libswresample 5. 3.100 / 5. 3.100
libpostproc 58. 3.100 / 58. 3.100
Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'.
Reading option '-i' ... matched as input url with argument 'little-metadata.opus'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument 9.
Successfully parsed a group of options.
Parsing a group of options: input url little-metadata.opus.
Successfully parsed a group of options.
Opening an input file: little-metadata.opus.
[AVFormatContext @ 0x1566054a0] Opening 'little-metadata.opus' for reading
[file @ 0x600000ece400] Setting default whitelist 'file,crypto,data'
Probing mp3 score:1 size:2048
Probing ogg score:100 size:2048
[ogg @ 0x1566054a0] Format ogg probed with size=2048 and score=100
[ogg @ 0x1566054a0] ogg_packet: curidx=-1
[ogg @ 0x1566054a0] ogg_packet: idx=0 pstart=0 psize=0 segp=0 nsegs=1
[ogg @ 0x1566054a0] ogg_packet: curidx=-1
[ogg @ 0x1566054a0] ogg_packet: idx=0 pstart=19 psize=0 segp=0 nsegs=1
[ogg @ 0x1566054a0] ogg_packet: curidx=-1
[ogg @ 0x1566054a0] ogg_packet: idx=0 pstart=87 psize=0 segp=0 nsegs=71
[ogg @ 0x1566054a0] found headers
[ogg @ 0x1566054a0] ogg_packet: curidx=-1
[ogg @ 0x1566054a0] ogg_packet: idx=0 pstart=0 psize=0 segp=0 nsegs=71
[ogg @ 0x1566054a0] Before avformat_find_stream_info() pos: 9179 bytes read:130843 seeks:3 nb_streams:1
For transform of length 120, inverse, mdct_float, flags: [aligned, out_of_place], found 5 matches:
1: mdct_pfa_15xM_inv_float_c - type: mdct_float, len: [30, ∞], factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only], prio: 304
2: mdct_pfa_5xM_inv_float_c - type: mdct_float, len: [10, ∞], factors[2]: [5, any], flags: [unaligned, out_of_place, inv_only], prio: 144
3: mdct_pfa_3xM_inv_float_c - type: mdct_float, len: [6, ∞], factors[2]: [3, any], flags: [unaligned, out_of_place, inv_only], prio: 112
4: mdct_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: 96
5: mdct_naive_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: -130976
For transform of length 4, inverse, fft_float, flags: [aligned, inplace, preshuf], found 2 matches:
1: fft4_fwd_float_neon - type: fft_float, len: 4, factor: 2, flags: [aligned, inplace, out_of_place, preshuf], prio: 352
2: fft4_ns_float_c - type: fft_float, len: 4, factor: 2, flags: [unaligned, inplace, out_of_place, preshuf], prio: 96
Transform tree:
mdct_pfa_15xM_inv_float_c - type: mdct_float, len: 120, factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only]
fft4_fwd_float_neon - type: fft_float, len: 4, factor: 2, flags: [aligned, inplace, out_of_place, preshuf]
For transform of length 240, inverse, mdct_float, flags: [aligned, out_of_place], found 5 matches:
1: mdct_pfa_15xM_inv_float_c - type: mdct_float, len: [30, ∞], factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only], prio: 304
2: mdct_pfa_5xM_inv_float_c - type: mdct_float, len: [10, ∞], factors[2]: [5, any], flags: [unaligned, out_of_place, inv_only], prio: 144
3: mdct_pfa_3xM_inv_float_c - type: mdct_float, len: [6, ∞], factors[2]: [3, any], flags: [unaligned, out_of_place, inv_only], prio: 112
4: mdct_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: 96
5: mdct_naive_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: -130976
For transform of length 8, inverse, fft_float, flags: [aligned, inplace, preshuf], found 3 matches:
1: fft8_ns_float_neon - type: fft_float, len: 8, factor: 2, flags: [aligned, inplace, out_of_place, preshuf], prio: 352
2: fft_pfa_ns_float_c - type: fft_float, len: [6, ∞], factors[2]: [7, 5, 3, 2, any], flags: [unaligned, inplace, out_of_place, preshuf], prio: 112
3: fft8_ns_float_c - type: fft_float, len: 8, factor: 2, flags: [unaligned, inplace, out_of_place, preshuf], prio: 96
Transform tree:
mdct_pfa_15xM_inv_float_c - type: mdct_float, len: 240, factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only]
fft8_ns_float_neon - type: fft_float, len: 8, factor: 2, flags: [aligned, inplace, out_of_place, preshuf]
For transform of length 480, inverse, mdct_float, flags: [aligned, out_of_place], found 5 matches:
1: mdct_pfa_15xM_inv_float_c - type: mdct_float, len: [30, ∞], factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only], prio: 304
2: mdct_pfa_5xM_inv_float_c - type: mdct_float, len: [10, ∞], factors[2]: [5, any], flags: [unaligned, out_of_place, inv_only], prio: 144
3: mdct_pfa_3xM_inv_float_c - type: mdct_float, len: [6, ∞], factors[2]: [3, any], flags: [unaligned, out_of_place, inv_only], prio: 112
4: mdct_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: 96
5: mdct_naive_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: -130976
For transform of length 16, inverse, fft_float, flags: [aligned, inplace, preshuf], found 3 matches:
1: fft16_ns_float_neon - type: fft_float, len: 16, factor: 2, flags: [aligned, inplace, out_of_place, preshuf], prio: 352
2: fft_pfa_ns_float_c - type: fft_float, len: [6, ∞], factors[2]: [7, 5, 3, 2, any], flags: [unaligned, inplace, out_of_place, preshuf], prio: 112
3: fft16_ns_float_c - type: fft_float, len: 16, factor: 2, flags: [unaligned, inplace, out_of_place, preshuf], prio: 96
Transform tree:
mdct_pfa_15xM_inv_float_c - type: mdct_float, len: 480, factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only]
fft16_ns_float_neon - type: fft_float, len: 16, factor: 2, flags: [aligned, inplace, out_of_place, preshuf]
For transform of length 960, inverse, mdct_float, flags: [aligned, out_of_place], found 5 matches:
1: mdct_pfa_15xM_inv_float_c - type: mdct_float, len: [30, ∞], factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only], prio: 304
2: mdct_pfa_5xM_inv_float_c - type: mdct_float, len: [10, ∞], factors[2]: [5, any], flags: [unaligned, out_of_place, inv_only], prio: 144
3: mdct_pfa_3xM_inv_float_c - type: mdct_float, len: [6, ∞], factors[2]: [3, any], flags: [unaligned, out_of_place, inv_only], prio: 112
4: mdct_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: 96
5: mdct_naive_inv_float_c - type: mdct_float, len: [2, ∞], factors[2]: [2, any], flags: [unaligned, out_of_place, inv_only], prio: -130976
For transform of length 32, inverse, fft_float, flags: [aligned, inplace, preshuf], found 3 matches:
1: fft32_ns_float_neon - type: fft_float, len: 32, factor: 2, flags: [aligned, inplace, out_of_place, preshuf], prio: 352
2: fft_pfa_ns_float_c - type: fft_float, len: [6, ∞], factors[2]: [7, 5, 3, 2, any], flags: [unaligned, inplace, out_of_place, preshuf], prio: 112
3: fft32_ns_float_c - type: fft_float, len: 32, factor: 2, flags: [unaligned, inplace, out_of_place, preshuf], prio: 96
Transform tree:
mdct_pfa_15xM_inv_float_c - type: mdct_float, len: 960, factors[2]: [15, any], flags: [unaligned, out_of_place, inv_only]
fft32_ns_float_neon - type: fft_float, len: 32, factor: 2, flags: [aligned, inplace, out_of_place, preshuf]
[ogg @ 0x1566054a0] ogg_packet: curidx=0
[ogg @ 0x1566054a0] ogg_packet: idx=0 pstart=87 psize=0 segp=0 nsegs=71
[opus @ 0x157804080] skip 312 / discard 0 samples due to side data
[opus @ 0x157804080] skip 312/960 samples
[ogg @ 0x1566054a0] All info found
[ogg @ 0x1566054a0] stream 0: start_time: 0.0075 duration: 211.7075
[ogg @ 0x1566054a0] format: start_time: 0.0075 duration: 211.7075 (estimate from stream) bitrate=119 kb/s
[ogg @ 0x1566054a0] After avformat_find_stream_info() pos: 9179 bytes read:130843 seeks:3 frames:1
Input #0, ogg, from 'little-metadata.opus':
Duration: 00:03:31.71, start: 0.007500, bitrate: 119 kb/s
Stream #0:0(eng), 1, 1/48000: Audio: opus, 48000 Hz, stereo, fltp, delay 312
Metadata:
encoder : Lavf61.7.100
Successfully opened the file.
Correcting start time of Input #0 by 9223372036854768307 us.
At least one output file must be specified
[AVIOContext @ 0x1567041f0] Statistics: 130843 bytes read, 3 seeks
I think I traced down why:
This boils down to some field names being changed according to ff_vorbiscomment_metadata_conv (libavformat/vorbiscomment.c).
If I understand the uses in ogg_write_vorbiscomment (libavformat/oggenc.c) and ff_vorbis_comment (libavformat/oggparsevorbis.c) correctly, during encoding the field name comment becomes DESCRIPTION and during decoding DESCRIPTION becomes comment again.
When looking at the code, the same should happen for flac.
This would mean that at least in the actual more-metadata.opus file the fields have the correct name. Unfortunately I wasn't able to find a flag to disable this nor any documentation about this conversion and would therefore call it at least unintuitive if not misleading.
I think the conversion during encoding to be fine, since it converts towards a standard. But I would expect ffprobe to show me what is written in a file and this makes it impossible to know the actual field name.


