Skip to content

Instantly share code, notes, and snippets.

@eyecatchup
Last active November 20, 2024 15:18
Show Gist options
  • Save eyecatchup/0757b3d8b989fe433979db2ea7d95a01 to your computer and use it in GitHub Desktop.
Save eyecatchup/0757b3d8b989fe433979db2ea7d95a01 to your computer and use it in GitHub Desktop.

Get/set ID3 meta tags using ffmpeg

A quick guide on how to read/write/modify ID3 metadata tags for audio / media files using ffmpeg.

FFmpeg has a free-form command line option that allows the user to specify key-value-pairs for encoding metadata. Let's take a look.

1. Read ID3 metadata

To list all global metadata tags for a media file, just set an input but no output file.

Code example(s):

ffmpeg -i file.mp3

Example 1: List all ID3 metadata tags for input file.


Unfortunately, there's no build-in option to get just a specific tag's value. But here's a bash one-liner to get that done.

# Get the value for the "title" ID3 metadata tag
ffmpeg -i file.mp3 2>&1 |grep -E '^\s*title\s*\:\s.*$' |awk -F ': ' '{print $2}'

Example 2: Get the value of a specific ID3 metadata tag for input file.

2. Write/modify ID3 metadata

To write "metadata" (a.k.a. ID3 metadata tags) to an audio file, or to modify or delete it, ffmpeg offers the -metadata option, which accepts metadata tags as key-value-pairs.

Here are some basic examples:

Code example(s):

The most basic use of the -metadata option is to set a single ID3 tag.

For example, to set the title tag for an mp3 file, use:

ffmpeg -i file.mp3 -metadata title="Track Title" out.mp3

Example 3: Set a single ID3 metadata tag.


You can also set multiple tags at once by creating an option list, as follows:

ffmpeg -i file.mp3 -metadata title="Track Title" -metadata artist="Rockstar" -metadata album="Hot Shit" out.mp3

Example 4: Set multiple ID3 metadata tags.

Description:

Adding, creating, deleting, or clearing ID3 tags with ffmpeg is very simple. The hard part is figuring out what items you want and what the correct tag key names are.

Whether the metadata key-value-pairs are actually encoded into the output file is dependent upon the file format being muxed. Many formats only support a handful of metadata keys.

For example, in Windows you can right-click on the audio file, select ‘Properties’, then click on the ‘Details’ tab. There are several Property/Value pair items listed; "Title", "Subtitle", "Comments", "Contributing artists", "Album artist", "Album", etcetera. Similar information is available in iTunes by right-clicking on a name, choose ‘Get Info’, then click on the ‘Info’ tab.

The following table tries to document which keys ffmpeg will encode into which formats.

Windows ID3v1.1 ID3v2.3 iTunes Low-level identifier ffmpeg key ffmpeg example
Title title TIT2 Name / Title \251nam title -metadata title="Track Title"
Subtitle n/a TIT3 Description ? TIT3 -metadata TIT3="Live-Edit"
Comments comment COMM Comments \251cmt comment -metadata comment="Extra info text"
? n/a ? Description \desc description -metadata description="Description text: Lorem ipsum ..."
Contributing artists artist TPE1 Artist \251ART artist -metadata artist="Artist Name"
Album artist n/a TPE2 Album Artist aART album_artist -metadata album_artist="Artist Name"
Album album TALB Album \251alb album -metadata album="Album Title"
Year year TYER Year \251day date -metadata date="1985"
# track TRCK Track Number trkn track -metadata track="2/5" (means 2 of 5)
? n/a TRACKTOTAL ? ? TRACKTOTAL -metadata TRACKTOTAL="12"
Part of set n/a TPOS Disc Number ? disc -metadata disc="1/3" (means 1 of 3)
Genre genreid TCON Genre \251gen genre -metadata genre="Rock"
? n/a ? Grouping \251grp grouping -metadata grouping="?"
Composer n/a ? Composer \251wrt composer -metadata composer="Composer Name"
Producer n/a ? Producer ? producer -metadata producer="Producer Name"
Publisher n/a ? ? ? publisher -metadata publisher="Publisher Name"
Copyright n/a ? ? \251cpy copyright -metadata copyright="(c) YYYY Copyright Holder Name"
Author URL n/a ? ? ? author_url -metadata author_url="http://example.com/"
? n/a ? ? ? encoder -metadata encoder="Lavf57.56.100"

I suggest you experiment with the different keys to find what works best for you.

But for now, lets look at some more (advanced) options you can use to manipulate metadata..

3. Clear/delete ID3 metadata

Deleting a global ID3 metadata tag is easy, too.

Code example(s):

To clear/delete a certain metadata tag, set the tag key but leave the value blank, like this:

ffmpeg -i file.mp3 -metadata album="" out.mp3

Example 5: Clear an ID3 metadata tag.


Now, if you want to clear/delete all global metadata tags in a file, you could use a command like in example 4 above and just include all the tag's key and a blank value for each item. Buuuut.. that could make your command line very long.

Instead you can use -map_metadata -1. Setting -map_metadata to -1 (negative one) tells ffmpeg to use a non-existent input, and thereby clearing/deleting all global metadata tags.

ffmpeg -i file.mp3 -map_metadata -1 out.mp3

Example 6: Delete/clear all global metadata tags.

4. Dump ID3 metadata to file

Another way to get and set ID3 metadata is to use ffmpeg's metadata muxer/demuxer with (ff)metadata files - simple UTF-8 encoded INI-like text files containing all global metadata information.

Code example(s):

To dump all metadata information of a media file to a (ff)metadata text file, use:

ffmpeg -i file.mp3 -f ffmetadata metadata.txt

Example 7: Dunp all global metadata of a media file to a (ff)metadata text file.

Description:

The MPEG audio file format is (roughly) as follows:

  • A file consists of a header and various metadata tags divided by linefeed-separated sections.
  • The header starts with the string ;FFMETADATA, followed by a version number.
  • Metadata tags are represented as key-value-pairs (key=value).
  • Immediately after the header follows global metadata.
  • After global metadata there may be sections with per-stream/per-chapter metadata.
  • A section starts with the section name in uppercase (i.e. STREAM or CHAPTER) in brackets ([, ]) and ends with a new/next section or end of file.
  • Empty lines and lines starting with ; or # are ignored.
  • Metadata keys or values containing special characters (=, ;, #, \ and a newline) must be escaped with a backslash (\).
  • Note that whitespace in metadata (e.g. "foo = bar") is considered to be a part of the tag (in the example above key is "foo ", value is " bar" (Notice the space after foo and before bar)).

Result:

The (ff)metadata text file that ffmpeg created from the command above, looks like this:

;FFMETADATA1
composer=Willie Royal
title=Napali
artist=Willie & Lobo
album=Caliente
genre=Jazz
track=2/11
date=1997
album_artist=Willie & Lobo

5. Load/apply ID3 metadata from file

Finally, we want to load all metadata for an media file from a (ff)metadata text file and then apply it to an output file.

Note: ffmpeg uses UTF-8 encoding. So, whenever you create or modify a (ff)metadata file, make sure your text editor supports (and uses) UTF-8 encoding!

Code example(s):

So, to load metadata from a (ff)metadata text file and create/encode an mp3 output file with ID3 v2.4 tags (default version) from it, type:

ffmpeg -i file.mp3 -i metadata.txt -map_metadata 1 -c:a libmp3lame -ar 44100 -b:a 192k -write_id3v2 1 -f mp3 out.mp3

Example 8: Encode an mp3 file, creating ID3 tags from a (ff)metadata text file.


If you are planning on using the media files with metadata on Windows, do not forget to use both the options to specify ID3 v1 and v2 versions as follows:

ffmpeg -i file.mp3 -i metadata.txt -map_metadata 1 -c:a libmp3lame -ar 44100 -b:a 192k -id3v2_version 3 -write_id3v1 1 -f mp3 out.mp3

Example 9: Encode an mp3 file, creating Windows-compatible ID3 tags from a (ff)metadata text file.

Description:

To help you understand all the options, lets break down that last command:

  • ffmpeg - call the ffmpeg programm
  • -i "file.mp3 - the media input file (input stream zero (0))
  • -i metadata.txt - the (ff)metadata text input file (input stream one (1))
  • -map_metadata 1 - tell ffmpeg where to find the metadata -
    a.k.a. map metadata to input stream one (1)
  • -ar 44100 - the output file audio sampling rate (in Hz)
  • -c:a libmp3lame - the output file audio codec to use to encode
  • -b:r 192k - the output file audio bit rate
  • -id3v2_version 3 - the ID3v2 version, force creating v2.3 tags (default: v2.4)
    (Required because Windows only supports version 3 of ID3v2 tags!)
  • -write_id3v1 1 - the ID3v1 version to create legacy v1.1 tags (disabled by default)
  • -f mp3 - the output file format (this will force a constant bit rate)
  • out.mp3 - the output file

6. Final notes

That is all there is to it. Pretty simple, he?

References, sources, helpful links:

@talhabalaj
Copy link

<3 Thanks, really helped me!

@deeeeekun
Copy link

Awesome! That table for different formats especially!

@sonyarianto
Copy link

sonyarianto commented Dec 26, 2020

@eyecatchup how to add new key value based on input metadata?
for example the input metadata has StreamTitle="Artist - Title" and we want to make metadata on the output become title="Artist - Title"

@eyecatchup
Copy link
Author

eyecatchup commented Jan 3, 2021

@eyecatchup how to add new key value based on input metadata?
for example the input metadata has StreamTitle="Artist - Title" and we want to make metadata on the output become title="Artist - Title"

Hey @sonyarianto, here's a one-liner you can use to set metadata tags dynamically, based on other tags:

ffmpeg -i file.mp3 -metadata title="`ffmpeg -i file.mp3 2>&1 |grep StreamTitle |awk -F ': ' '{print $2}'`" outfile-with-new-metadata.mp3

@alil0rd
Copy link

alil0rd commented Jan 22, 2021

It is great! Thanks

@h1z1
Copy link

h1z1 commented Nov 16, 2021

FWIW you can avoid the grep/awk parse with ffprobe. ie

[%] ffprobe -hide_banner  -loglevel fatal   -show_entries format_tags -of flat   -i out.mkv
format.tags.title="foo"
format.tags.DATE="20211110"
[%]
[%]  ffprobe -hide_banner  -loglevel fatal   -show_entries format_tags=title -of flat   -i out.mkv
format.tags.title="foo"
[%]

Advantage is you can leverage everything else ffprobe supports like stream selection and output formats (-of json for example).

+1 for the list

@Niols
Copy link

Niols commented Mar 23, 2022

Thank you!

@Paderman
Copy link

I want to use metadata for a HLS stream, but commonly it accept title and for audio tracks language only.
What metadata are supported in HLS?

I want to fill metadata like date and similar, that can be for example show in VLC, but nothing works…

@isaacwaldron
Copy link

Great reference, thank you! I found that Windows 11 at least is now supporting the ID3v2.4 tags that ffmpeg writes by default.

@goodarzi
Copy link

goodarzi commented Mar 4, 2024

Use -c copy option in cases where only metadata changed.
it will prevent ffmpeg from re-encoding mp3 and commits the changes on the fly.

@slmjkdbtl
Copy link

Thanks for the info!

There's a possible caveat with the

$ ffmpeg -i file.mp3 2>&1 | grep -E '^\s*title\s*\:\s.*$' | awk -F ': ' '{print $2}'

script for getting specific id3tag fields. Some music files may have "title" metadata in other streams, in my case I want to get the comment tag but there's also a comment field in stream 0:1

$ ffprobe -hide_banner test.mp3
Input #0, mp3, from 'test.mp3':
  Metadata:
    encoder         : Lavf60.16.100
    artist          : Ray Bryant
    album           : Sound Ray
    date            : 1969
    title           : A Song For My Father
    album_artist    : Ray Bryant
    track           : 1/8
    disc            : 1/1
    genre           : jazzz
    grouping        : testgroup
    comment         : examplecomment                           <--- comment
  Duration: 00:05:23.45, start: 0.023021, bitrate: 259 kb/s
  Stream #0:0: Audio: mp3, 48000 Hz, stereo, fltp, 256 kb/s
    Metadata:
      encoder         : LAME3.100
  Stream #0:1: Video: mjpeg (Baseline), yuvj420p(pc, bt470bg/unknown/unknown), 580x580 [SAR 96:96 DAR 1:1], 90k tbr, 90k tbn (attached pic)
    Metadata:
      comment         : Other                                  <--- comment

$ ffmpeg -i test.mp3 2>&1 | grep -E '^\s*comment\s*\:\s.*$' | awk -F ': ' '{print $2}'
examplecomment
Other                         <--- this I don't want!

I had to put another sed into the pipe to only output things before "Duration" so it only outputs id3tag info

$ ffmpeg -i test.mp3 2>&1 | sed -n '/Duration:/q;p' | grep -E '^\s*comment\s*\:\s.*$' | awk -F ': ' '{print $2}'
examplecomment

Or if anyone knows a better approach than sed, please let me know!

@niteshrawat1995
Copy link

Can we add timed id3 tags on mp4 files as well?

@johncrichton
Copy link

Does anyone know, how can ffmpeg print out Metadata like StreamTitle continuously? For example, I will listen to a stream and the incoming metadata will change every 20 minutes. At the moment with above examples, ffmpeg will only print out metadata it read at the start and will not react to changing of said metadata.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment