How youtube-dl Implements Metadata Writing and xattr Support: A Deep Dive into the Source Code
youtube-dl embeds metadata into media files using FFmpeg via the --add-metadata flag and writes extended filesystem attributes via the --xattrs flag through dedicated Python post-processors.
The ytdl-org/youtube-dl repository provides two distinct mechanisms for attaching metadata to downloaded content: container-level embedding through FFmpeg and extended attribute (xattr) storage for filesystems that support them. Both implementations reside in the post-processor subsystem and are triggered by specific command-line options defined in the core configuration.
Embedding Metadata with FFmpeg in youtube-dl
When users invoke the --add-metadata option, youtube-dl triggers the FFmpegMetadataPP post-processor to rewrite the media container with embedded tags.
Command-Line Option Configuration
The --add-metadata switch is defined in youtube_dl/options.py at lines 846-848. The parser stores this as a boolean flag in the addmetadata destination:
# From youtube_dl/options.py
parser.add_option('--add-metadata',
action='store_true', dest='addmetadata', default=False,
help='Write metadata to the video file')
The FFmpegMetadataPP Post-Processor Implementation
The core logic lives in youtube_dl/postprocessor/ffmpeg.py starting at line 429. The FFmpegMetadataPP class extends FFmpegPostProcessor and implements the run() method to modify files after download completion.
Metadata Mapping and FFmpeg Command Construction
Inside FFmpegMetadataPP.run(), the code constructs a metadata dictionary mapping standard fields to FFmpeg-compatible keys. Supported fields include title, artist, album, track, genre, and date (lines 431-447).
The post-processor builds FFmpeg arguments dynamically:
# Conceptual flow from youtube_dl/postprocessor/ffmpeg.py
options = []
for name, value in metadata.items():
options.extend(['-metadata', f'{name}={value}'])
If chapter information exists, the code writes a temporary metadata file in FFmpeg's ;FFMETADATA1 format and appends -map_metadata 1 to the command (lines 482-504). The final command re-encodes the container while preserving streams, embedding the metadata directly into the output file.
Usage Example
youtube-dl --add-metadata -o "%(title)s.%(ext)s" "https://www.youtube.com/watch?v=example"
This command downloads the video and embeds title, artist, and date tags into the media container, visible in players like VLC or MPV.
Implementing Extended Attribute (xattr) Support in youtube-dl
The --xattrs option enables storage of metadata as extended filesystem attributes, compatible with Linux (ext4, XFS, Btrfs) and macOS (HFS+, APFS) filesystems.
Enabling xattr Writing via Command-Line Flags
The option is defined in youtube_dl/options.py at lines 859-861:
# From youtube_dl/options.py
parser.add_option('--xattrs',
action='store_true', dest='xattrs', default=False,
help='Write metadata to the file\'s xattrs')
In youtube_dl/__init__.py around line 279, the initialization logic checks opts.xattrs and appends XAttrMetadataPP to the post-processor chain.
The XAttrMetadataPP Post-Processor
The implementation resides in youtube_dl/postprocessor/xattrpp.py starting at line 13. The XAttrMetadataPP class defines a mapping between Dublin Core/XDG attribute names and youtube-dl's internal info dictionary fields.
Attribute Mapping and the write_xattr Utility
The mapping dictionary at lines 34-43 defines standard attributes:
# From youtube_dl/postprocessor/xattrpp.py
xattr_mapping = {
'user.dublincore.title': 'title',
'user.dublincore.date': 'upload_date',
'user.dublincore.description': 'description',
'user.dublincore.creator': 'uploader',
'user.dublincore.publisher': 'uploader',
'user.xdg.referrer.url': 'webpage_url',
}
The run() method iterates this mapping, encodes values as UTF-8, and calls write_xattr(filename, xattrname, byte_value) (lines 45-56).
The write_xattr helper function in youtube_dl/utils.py (line 6166) abstracts OS-specific syscalls. On Linux, it uses ctypes to invoke setxattr with the XATTR_CREATE flag; on macOS, it uses setxattr from the ctypes wrapper for the C library.
Error Handling for xattr Operations
The post-processor catches specific exceptions defined in youtube_dl/utils.py. At lines 60-78 in xattrpp.py, the code handles:
- XAttrUnavailableError: Filesystem does not support xattrs
- XAttrMetadataError: Value too long or insufficient disk space
- XAttrPermissionError: Permission denied when writing attributes
When these errors occur, youtube-dl logs a warning but continues processing, ensuring that metadata failures do not interrupt the download workflow.
Usage Example
# Download with xattr metadata storage
youtube-dl --xattrs -o "%(title)s.%(ext)s" "https://vimeo.com/12345678"
# Verify extended attributes on Linux
getfattr -d -m "user.*" "MyVideo.mp4"
This writes attributes such as user.dublincore.title and user.dublincore.creator to the file, readable via standard xattr tools.
Key Source Files for youtube-dl Metadata and xattr Features
Understanding the implementation requires familiarity with these specific modules:
-
youtube_dl/options.py– Defines the--add-metadataand--xattrsCLI switches at lines 846-848 and 859-861. -
youtube_dl/__init__.py– Orchestrates post-processor initialization around line 279, checking option flags and appending the appropriate processors to the download pipeline. -
youtube_dl/postprocessor/ffmpeg.py– ContainsFFmpegMetadataPP(lines 429-504), which constructs FFmpeg commands to embed metadata into media containers. -
youtube_dl/postprocessor/xattrpp.py– HousesXAttrMetadataPP(lines 13-78), implementing the Dublin Core/XDG attribute mapping and xattr writing logic. -
youtube_dl/utils.py– Provides thewrite_xattrhelper (line 6166) and exception classes (XAttrMetadataError,XAttrUnavailableError) used by the xattr post-processor.
Practical Usage Summary
| Goal | Command | Result |
|---|---|---|
| Embed container metadata | youtube-dl --add-metadata <URL> |
FFmpeg rewrites the file with ID3/MP4 tags (title, artist, date) visible in media players. |
| Store filesystem xattrs | youtube-dl --xattrs <URL> |
Writes Dublin Core attributes (user.dublincore.title, etc.) to the file's extended attributes. |
| Both methods | youtube-dl --add-metadata --xattrs <URL> |
Embeds metadata in the container and writes xattrs for filesystem-level metadata retrieval. |
These options operate independently; enable both when you need metadata accessible to both media players and file management tools.
Summary
-
FFmpegMetadataPP in
youtube_dl/postprocessor/ffmpeg.pyhandles--add-metadataby constructing FFmpeg-metadataarguments and temporary chapter files to embed tags directly into media containers. -
XAttrMetadataPP in
youtube_dl/postprocessor/xattrpp.pyimplements--xattrsby mapping info fields to Dublin Core/XDG names and callingwrite_xattrfromyoutube_dl/utils.pyto set extended filesystem attributes. -
Both features are opt-in via CLI flags defined in
youtube_dl/options.pyand are conditionally added to the post-processor chain inyoutube_dl/__init__.pybased on user selection.
Frequently Asked Questions
What is the difference between --add-metadata and --xattrs in youtube-dl?
The --add-metadata flag embeds metadata directly into the media file's container format (such as MP4 or MKV) using FFmpeg, making the tags visible to media players like VLC. The --xattrs flag writes metadata as extended filesystem attributes (xattrs) using the XAttrMetadataPP post-processor, storing Dublin Core fields like user.dublincore.title that are accessible via command-line tools like getfattr but invisible to most media players.
Which metadata fields does youtube-dl embed when using --add-metadata?
According to the FFmpegMetadataPP implementation in youtube_dl/postprocessor/ffmpeg.py, youtube-dl maps the following info dictionary fields to FFmpeg metadata tags: title, artist, album, track, genre, and date (upload date). If the video contains chapters, the post-processor also generates a temporary FFmetadata file and passes -map_metadata 1 to FFmpeg to preserve chapter markers alongside the tags.
How does youtube-dl handle filesystems that do not support extended attributes?
The XAttrMetadataPP class in youtube_dl/postprocessor/xattrpp.py catches specific exceptions when calling write_xattr from youtube_dl/utils.py. If the filesystem does not support xattrs, an XAttrUnavailableError is raised and caught, causing youtube-dl to log a warning and continue without failing the download. Similarly, XAttrMetadataError handles cases where values are too long or disk space is insufficient, ensuring robust operation across diverse filesystems.
Can I use both --add-metadata and --xattrs simultaneously in youtube-dl?
Yes, both options are independent and can be combined in a single command. When you run youtube-dl --add-metadata --xattrs <URL>, the downloader first completes the download, then executes FFmpegMetadataPP to embed tags into the media container, followed by XAttrMetadataPP to write Dublin Core attributes to the filesystem. This dual approach ensures metadata is accessible to media players (via container tags) and to file management scripts or desktop search tools (via extended attributes).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →