# How youtube-dl Implements Metadata Writing and xattr Support: A Deep Dive into the Source Code

> Discover how youtube-dl writes metadata and xattr support. Explore the source code to understand its advanced file processing capabilities.

- Repository: [youtube-dl/youtube-dl](https://github.com/ytdl-org/youtube-dl)
- Tags: deep-dive
- Published: 2026-02-25

---

**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`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/options.py) at lines 846-848. The parser stores this as a boolean flag in the `addmetadata` destination:

```python

# 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`](https://github.com/ytdl-org/youtube-dl/blob/main/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:

```python

# 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

```bash
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`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/options.py) at lines 859-861:

```python

# 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`](https://github.com/ytdl-org/youtube-dl/blob/main/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`](https://github.com/ytdl-org/youtube-dl/blob/main/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:

```python

# 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`](https://github.com/ytdl-org/youtube-dl/blob/main/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`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/utils.py). At lines 60-78 in [`xattrpp.py`](https://github.com/ytdl-org/youtube-dl/blob/main/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

```bash

# 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`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/options.py)** – Defines the `--add-metadata` and `--xattrs` CLI switches at lines 846-848 and 859-861.

- **[`youtube_dl/__init__.py`](https://github.com/ytdl-org/youtube-dl/blob/main/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`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/postprocessor/ffmpeg.py)** – Contains `FFmpegMetadataPP` (lines 429-504), which constructs FFmpeg commands to embed metadata into media containers.

- **[`youtube_dl/postprocessor/xattrpp.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/postprocessor/xattrpp.py)** – Houses `XAttrMetadataPP` (lines 13-78), implementing the Dublin Core/XDG attribute mapping and xattr writing logic.

- **[`youtube_dl/utils.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/utils.py)** – Provides the `write_xattr` helper (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.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/postprocessor/ffmpeg.py) handles `--add-metadata` by constructing FFmpeg `-metadata` arguments and temporary chapter files to embed tags directly into media containers.

- **XAttrMetadataPP** in [`youtube_dl/postprocessor/xattrpp.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/postprocessor/xattrpp.py) implements `--xattrs` by mapping info fields to Dublin Core/XDG names and calling `write_xattr` from [`youtube_dl/utils.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/utils.py) to set extended filesystem attributes.

- Both features are opt-in via CLI flags defined in [`youtube_dl/options.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/options.py) and are conditionally added to the post-processor chain in [`youtube_dl/__init__.py`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/__init__.py) based 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`](https://github.com/ytdl-org/youtube-dl/blob/main/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`](https://github.com/ytdl-org/youtube-dl/blob/main/youtube_dl/postprocessor/xattrpp.py) catches specific exceptions when calling `write_xattr` from [`youtube_dl/utils.py`](https://github.com/ytdl-org/youtube-dl/blob/main/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).