{
  "schemaVersion": 1,
  "contentVersion": "ca42e61ede0a24f789d7287a0001244ad22f4abf",
  "id": "docs/guides/audio-and-subtitles",
  "collection": "docs",
  "title": "Audio and subtitles",
  "description": "Keep, re-encode, label and synchronize audio and subtitle tracks with FFmpeg, convert subtitles for MP4, and burn subtitles into the picture.",
  "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/",
  "apiUrl": "https://encode.wiki/api/v1/documents/docs/guides/audio-and-subtitles.json",
  "markdownUrl": "https://encode.wiki/api/v1/markdown/docs/guides/audio-and-subtitles.md",
  "status": "current",
  "tags": [
    "audio",
    "subtitles",
    "ffmpeg"
  ],
  "license": "CC BY-SA 4.0",
  "dates": {
    "lastVerified": "2026-10-08T00:00:00.000Z"
  },
  "authors": [],
  "sources": [
    {
      "title": "FFmpeg documentation — stream specifiers, mapping, metadata and dispositions",
      "url": "https://ffmpeg.org/ffmpeg.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "FFmpeg filters — subtitles and overlay",
      "url": "https://ffmpeg.org/ffmpeg-filters.html#subtitles-1",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "Matroska — subtitle mappings",
      "url": "https://www.matroska.org/technical/subtitles.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "libass — ASS file format guide (fonts)",
      "url": "https://github.com/libass/libass/wiki/ASS-File-Format-Guide",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "MKVToolNix — mkvmerge documentation",
      "url": "https://mkvtoolnix.download/doc/mkvmerge.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "Xiph.org — Opus recommended settings",
      "url": "https://wiki.xiph.org/Opus_Recommended_Settings",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "FFmpeg libopusenc.c at n9.0.2 (layout check and mapping families)",
      "url": "https://github.com/FFmpeg/FFmpeg/blob/n9.0.2/libavcodec/libopusenc.c",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    }
  ],
  "headings": [
    {
      "depth": 2,
      "text": "Stream numbering",
      "anchor": "stream-numbering"
    },
    {
      "depth": 2,
      "text": "Keep everything and change nothing",
      "anchor": "keep-everything-and-change-nothing"
    },
    {
      "depth": 2,
      "text": "Re-encode audio, copy the rest",
      "anchor": "re-encode-audio-copy-the-rest"
    },
    {
      "depth": 2,
      "text": "Set languages, titles and default tracks",
      "anchor": "set-languages-titles-and-default-tracks"
    },
    {
      "depth": 2,
      "text": "Subtitles in MP4 and on the web",
      "anchor": "subtitles-in-mp4-and-on-the-web"
    },
    {
      "depth": 2,
      "text": "Fonts for ASS subtitles",
      "anchor": "fonts-for-ass-subtitles"
    },
    {
      "depth": 2,
      "text": "Burn subtitles into the picture",
      "anchor": "burn-subtitles-into-the-picture"
    },
    {
      "depth": 2,
      "text": "Fix audio that is out of sync",
      "anchor": "fix-audio-that-is-out-of-sync"
    }
  ],
  "sections": [
    {
      "id": "_preamble",
      "title": "Page introduction",
      "depth": 0,
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/_preamble.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/_preamble.md",
      "checksum": "151ef1fcd6055670a66df4d3f09255b6f6c7fb4ff766deafafffdccc36e44237",
      "bytes": 319
    },
    {
      "id": "stream-numbering",
      "title": "Stream numbering",
      "depth": 2,
      "anchor": "stream-numbering",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#stream-numbering",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/stream-numbering.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/stream-numbering.md",
      "checksum": "a9fccbe1e6d8ce3fadc9f45c1e08e1bc612fdded586a45a452cf88bf289ed95e",
      "bytes": 610
    },
    {
      "id": "keep-everything-and-change-nothing",
      "title": "Keep everything and change nothing",
      "depth": 2,
      "anchor": "keep-everything-and-change-nothing",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#keep-everything-and-change-nothing",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/keep-everything-and-change-nothing.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/keep-everything-and-change-nothing.md",
      "checksum": "df9ad55d07174dc5dc5c164e288df66311c195a8c92cf514629ad063ad4982fe",
      "bytes": 774
    },
    {
      "id": "re-encode-audio-copy-the-rest",
      "title": "Re-encode audio, copy the rest",
      "depth": 2,
      "anchor": "re-encode-audio-copy-the-rest",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#re-encode-audio-copy-the-rest",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/re-encode-audio-copy-the-rest.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/re-encode-audio-copy-the-rest.md",
      "checksum": "3fb2cd41c03318d77cd55a2fb1dcd14d221a00262103565e1696c3b5928ce598",
      "bytes": 1257
    },
    {
      "id": "set-languages-titles-and-default-tracks",
      "title": "Set languages, titles and default tracks",
      "depth": 2,
      "anchor": "set-languages-titles-and-default-tracks",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#set-languages-titles-and-default-tracks",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/set-languages-titles-and-default-tracks.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/set-languages-titles-and-default-tracks.md",
      "checksum": "6f59c7c295c11ab8b8a6f5a237cf7b58bffeb144f64073525e3e4fe073abdc86",
      "bytes": 809
    },
    {
      "id": "subtitles-in-mp4-and-on-the-web",
      "title": "Subtitles in MP4 and on the web",
      "depth": 2,
      "anchor": "subtitles-in-mp4-and-on-the-web",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#subtitles-in-mp4-and-on-the-web",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/subtitles-in-mp4-and-on-the-web.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/subtitles-in-mp4-and-on-the-web.md",
      "checksum": "c43092ff3ed6b4b0695a22989fd478ff33ef4b3976987b16f7a9669ead23463b",
      "bytes": 1697
    },
    {
      "id": "fonts-for-ass-subtitles",
      "title": "Fonts for ASS subtitles",
      "depth": 2,
      "anchor": "fonts-for-ass-subtitles",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#fonts-for-ass-subtitles",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/fonts-for-ass-subtitles.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/fonts-for-ass-subtitles.md",
      "checksum": "5854ebaa29eab141cc9db2bce3a66e0c9377ecdb16c171135934f883d2f5a45d",
      "bytes": 397
    },
    {
      "id": "burn-subtitles-into-the-picture",
      "title": "Burn subtitles into the picture",
      "depth": 2,
      "anchor": "burn-subtitles-into-the-picture",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#burn-subtitles-into-the-picture",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/burn-subtitles-into-the-picture.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/burn-subtitles-into-the-picture.md",
      "checksum": "b684870e08098786b96eb6852e2dea9f5a98fd61e600d8a4bce9721a50b6e3ef",
      "bytes": 1071
    },
    {
      "id": "fix-audio-that-is-out-of-sync",
      "title": "Fix audio that is out of sync",
      "depth": 2,
      "anchor": "fix-audio-that-is-out-of-sync",
      "canonicalUrl": "https://encode.wiki/guides/audio-and-subtitles/#fix-audio-that-is-out-of-sync",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/fix-audio-that-is-out-of-sync.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/guides/audio-and-subtitles/fix-audio-that-is-out-of-sync.md",
      "checksum": "3ddff032faab88286affbc5e4e32d56a2b8d773d79b7400354c3d79073334ce7",
      "bytes": 791
    }
  ],
  "outboundReferences": [
    "/codecs/subtitles/srt/",
    "/codecs/subtitles/ssa/",
    "/codecs/subtitles/webvtt/",
    "/tools/utilities/mkvtoolnix/"
  ],
  "checksum": "41a5ccc8d423e61cdb8edd94121c9b75b45bf17c84ab334c687ddeb9841f42b7",
  "contentFormat": "markdown",
  "markdown": "A film or episode usually carries more than one video and one audio stream: several languages,\ncommentary, full and forced subtitles, chapters and attached fonts. This guide covers keeping the\nones you want, re-encoding audio, labelling tracks, getting subtitles into MP4, burning subtitles in,\nand fixing audio delay.\n\n## Stream numbering\n\nRun `ffprobe -hide_banner input.mkv` to list the streams. FFmpeg's stream specifiers count in two\nways:\n\n- `0:3` is stream 3 of input 0, counting all streams.\n- `0:a:1` is the second **audio** stream of input 0, counting only that type from zero.\n\nOptions that act on output streams, such as `-c:a:1` or `-metadata:s:a:1`, use the numbering of the\n**output** file. If you map the source's second audio track first, it becomes output `a:0`.\n\nOnce you use `-map`, FFmpeg writes only the streams you list. Without it, it keeps one video, one\naudio and one subtitle stream and drops the rest.\n\n## Keep everything and change nothing\n\n```sh\nffmpeg -i input.mkv -map 0 -c copy output.mkv\n```\n\n`-map 0` takes every stream, including attachments such as fonts; `-c copy` copies them without\nre-encoding. Chapters and global metadata are copied by default. This is how you change container\nor drop tracks without any quality loss. For detailed Matroska editing (track order, flags, header\nedits without remuxing) [MKVToolNix](/tools/utilities/mkvtoolnix/) is often more convenient.\n\nTo drop tracks, map selectively. This keeps the video, the first audio track and every subtitle\nstream (`?` makes the subtitle map optional; the quotes stop zsh from treating `?` as a wildcard):\n\n```sh\nffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -map '0:s?' -map '0:t?' -c copy output.mkv\n```\n\n## Re-encode audio, copy the rest\n\n```sh\nffmpeg -i input.mkv -map 0 -c copy -c:a libopus -b:a:0 128k -b:a:1 256k output.mkv\n```\n\n`-c copy` applies to everything and `-c:a libopus` then overrides it for audio. Set bitrates per\noutput stream: about 128 kbit/s for stereo and 256 kbit/s for 5.1 are good Opus starting points.\n\nlibopus rejects the common `5.1(side)` layout with `Invalid channel layout 5.1(side) for specified\nmapping family`, and `-mapping_family 1` on its own does not change that. Convert the surround\ntrack to plain 5.1 with a filter that targets only that output stream:\n\n```sh\nffmpeg -i input.mkv -map 0 -c copy -c:a libopus -b:a:0 128k -b:a:1 256k \\\n  -filter:a:1 aformat=channel_layouts=5.1 -mapping_family:a:1 1 output.mkv\n```\n\n`aformat` moves the side channels to the back positions without downmixing. A bare `-af` would\napply to every audio stream and upmix the stereo track to 5.1 as well. `-mapping_family 1` switches\nlibopus to its surround encoder, which uses masking between channels to spend the bits better.\n\nCopy audio that already plays on your targets. Re-encoding a lossy track (AC-3, DTS, AAC) adds\nanother generation of loss; re-encoding lossless tracks (FLAC, PCM, TrueHD, DTS-HD MA) to Opus saves\nmost of their size.\n\n## Set languages, titles and default tracks\n\n```sh\nffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -map 0:a:1 -map 0:s:0 -c copy \\\n  -metadata:s:a:0 language=eng -metadata:s:a:0 title=\"Stereo\" \\\n  -metadata:s:a:1 language=jpn \\\n  -disposition:a:0 default -disposition:a:1 0 -disposition:s:0 0 \\\n  output.mkv\n```\n\nLanguages are ISO 639-2 codes (`eng`, `jpn`, `ger`…). A disposition value replaces all of that\nstream's flags, so `0` clears them. Players use the `default` flag when the viewer has no language\npreference; they may ignore it when one is set.\n\nA **forced** subtitle track holds only what should appear when full subtitles are off, such as\ntranslated signs and foreign-language lines. Mark such a track with `-disposition:s:0 forced`. The\nflag does not extract forced lines from a full subtitle track.\n\n## Subtitles in MP4 and on the web\n\n| Target                           | Subtitle format                                                                          | Notes                                                                       |\n| -------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |\n| MKV                              | Copy anything: [SRT](/codecs/subtitles/srt/), [ASS](/codecs/subtitles/ssa/), PGS, VobSub | Keep ASS fonts as attachments.                                              |\n| MP4                              | `mov_text` (converted from SRT or ASS)                                                   | ASS styling and positioning are lost. Bitmap subtitles cannot be converted. |\n| HTML `<video>`                   | External [WebVTT](/codecs/subtitles/webvtt/) file in a `<track>` element                 | Most browsers ignore subtitle tracks embedded in the video file.            |\n| Players without subtitle support | Burn in (below)                                                                          | Cannot be turned off.                                                       |\n\nAn MP4 with AAC audio and text subtitles converted to `mov_text`:\n\n```sh\nffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -map 0:s:0 \\\n  -c:v copy -c:a aac -b:a 192k -c:s mov_text -movflags +faststart output.mp4\n```\n\n`-movflags +faststart` moves the MP4 index to the front so web playback can start before the file\nhas fully downloaded. Turning PGS or VobSub (bitmap) subtitles into text needs OCR, for example\nwith Subtitle Edit.\n\n## Fonts for ASS subtitles\n\nASS styles refer to fonts by family name, so the fonts have to travel with the file. In MKV they are\nstored as attachments; `-map 0` (or `-map '0:t?'`) keeps them. To add a font, use mkvmerge:\n\n```sh\nmkvmerge -o output.mkv input.mkv --attach-file MyFont-Regular.ttf\n```\n\nInclude the bold and italic faces the script uses, and only attach fonts whose licence allows it.\n\n## Burn subtitles into the picture\n\nBurning in renders the subtitles onto the video, so the video must be re-encoded. For text\nsubtitles (SRT, ASS) use the `subtitles` filter. It needs an FFmpeg build with libass, and it loads\nfonts attached to the file:\n\n```sh\nffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -vf \"subtitles=input.mkv:si=0\" \\\n  -c:v libx264 -preset slow -crf 20 -c:a copy output.mkv\n```\n\n`si=0` picks the first subtitle stream in the file. For an external file use\n`subtitles=captions.ass`, and add `:fontsdir=fonts` if its fonts are in a separate directory.\n\nFor bitmap subtitles (PGS, VobSub, DVB), overlay them instead:\n\n```sh\nffmpeg -i input.mkv -filter_complex \"[0:v][0:s:0]overlay=shortest=1\" -map 0:a:0 \\\n  -c:v libx264 -preset slow -crf 20 -c:a copy output.mkv\n```\n\n`shortest=1` ends the output with the video; without it the last subtitle event can stretch the\noutput far past the end. The subtitle canvas must match the video size; if it does not (for example after cropping or\nscaling), scale or crop the video after the overlay rather than before.\n\n## Fix audio that is out of sync\n\nCheck sync near the start, middle and end. A constant offset is a delay you can fix with timestamps.\nDrift that grows over time comes from a frame-rate or speed mismatch (for example a 25 fps PAL track\nagainst a 23.976 fps video) and needs the audio to be time-stretched or resampled instead.\n\nTo delay an audio track by 250 ms, offset the input it comes from:\n\n```sh\nffmpeg -i video.mkv -itsoffset 0.250 -i audio.mka -map 0:v:0 -map 1:a:0 -c copy output.mkv\n```\n\n`-itsoffset` applies to the input that follows it; use a negative value to make the audio earlier.\nThe same input can be opened twice (`-i input.mkv -itsoffset 0.250 -i input.mkv`) to shift a track\nwithin one file. In MKVToolNix the equivalent is the track's delay setting\n(`--sync TID:250`).\n"
}
