Jump to content

External audio tracks (sidecar `.mka` / `.m4a`) are silent when subtitles are enabled, and after resume/seek


Recommended Posts

Gu1llohm
Posted

**Server:** Emby Server 4.10.1.0 and 4.10.2.0, macOS arm64 (Mac Studio M3 Ultra), bundled ffmpeg `5.1-emby_2023_06_25_p6`
**Clients tested:** Emby for iOS 2.2.59, Emby for macOS 2.2.59, Emby Web 4.10.2.0 (Firefox) — all affected
**Media:** `Movie.mkv` with an external audio file next to it, e.g. `Movie.rus.mka` (AC3) or `Movie.rus.m4a` (AAC). Emby detects it correctly as an external audio stream ("Russian AC3" / "Russian AAC").

## Symptoms
- Selecting the external audio track gives **no sound** when the movie is resumed, after seeking, and — most of the time — whenever subtitles are displayed, even from the start.
- The files themselves are fine (normal levels on all channels), and the internal audio tracks of the same movie play normally.
- Direct play is never used for this case: the server always remuxes/transcodes (`TranscodeReasons: ExternalAudioNotSupported`).

## Root cause 1 — the resume/seek position is not applied to the external audio input
Emby builds (shortened, from the ffmpeg remux log):

```
ffmpeg -copyts -start_at_zero -f matroska,webm -ss 00:27:54.000 -noaccurate_seek -i "Movie.mkv" \
       -f mov,mp4,m4a,3gp,3g2,mj2 -i "Movie.rus.m4a" -map 0:0 -map 1:0 ... -f segment ...
```

`-ss` is only applied to the first input. With `-copyts`, the external audio keeps starting at 0, i.e. minutes before the video, and players drop it.

Measured on the produced segments (*127 Hours*, `.rus.mka`, resume at 20:00):

| | first video pts | first external-audio pts |
|---|---|---|
| Emby command as generated | ~1208 s | **10 s** |
| + `-ss 00:20:00.000 -noaccurate_seek` before the external `-i` | ~1208 s | **~1208 s** |

Note: an *accurate* seek on that input (`-ss` without `-noaccurate_seek`), combined with `-copyts`, removes the audio from the output entirely in our tests — the seek must be `-noaccurate_seek`.

## Root cause 2 — subtitle outputs starve the external audio input
When the client also requests subtitles, Emby adds extra outputs to the same ffmpeg process
(`-map 0:3 -vn -an -c:s:0 webvtt -f segment ...`). In that configuration ffmpeg no longer interleaves the external audio input. Replaying Emby's exact command (resume at 10:27, subtitles on):

| Variant of the exact Emby command | audio packets in the first 5 HLS segments |
|---|---|
| as generated (+ fix 1) | 1, 0, 0, 0, 0 — **one packet for the whole movie** |
| without the subtitle outputs | 183, 93, 94, 92, 93 |
| with `-max_interleave_delta 0` on each output | 183, 93, 94, 92, 90 (subtitles still produced: 1820 `.vtt` segments) |
| reference: same movie, internal audio track | ~93 per 3 s segment |

`-max_muxing_queue_size`, `-thread_queue_size` and removing `-max_delay` do not help; `-max_interleave_delta 100000` does not either — only `0` works.

## Suggested fix in Emby
When an external audio stream is added as an extra input:
1. pass the same seek as the main input before that `-i`: `-ss <position> -noaccurate_seek`;
2. add `-max_interleave_delta 0` to the outputs.

## Workaround we use (works on iOS, macOS and Web)
A small wrapper installed in place of the bundled `ffmpeg` (real binary renamed `ffmpeg.emby`). It only changes commands that contain an external `.rus/.ukr.mka|m4a|ac3` input and passes everything else through unchanged:

```python
#!/usr/bin/python3
# Wrapper for Emby's bundled ffmpeg: fixes silent external audio tracks.
# 1. copy the main input's -ss before the external audio input (-noaccurate_seek)
# 2. add -max_interleave_delta 0 before each output format (-f) after the inputs
import os, re, sys, time
REAL = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ffmpeg.emby")
LOG = os.path.expanduser("~/.config/emby-server/logs/ffmpeg-wrapper.log")
EXTERNAL = re.compile(r"\.(rus|ukr)\.(mka|m4a|ac3)$", re.I)   # adapt to your languages

def fix(a):
    inputs = [i for i, x in enumerate(a) if x == "-i" and i + 1 < len(a)]
    ext = [i for i in inputs[1:] if EXTERNAL.search(a[i + 1])]
    if not ext:
        return a, ""
    pos = next((a[i + 1] for i in range(inputs[0]) if a[i] == "-ss" and i + 1 < len(a)), None)
    notes, extra = [], {}
    for i in ext:
        start = max([e for e in inputs if e < i], default=-1) + 2
        if pos and "-ss" not in a[start:i]:
            extra[i] = ["-ss", pos, "-noaccurate_seek"]
            notes.append(f"seek {pos} -> {os.path.basename(a[i + 1])}")
    last = inputs[-1] + 2
    out = []
    for k, x in enumerate(a):
        if k in extra:
            out += extra[k]
        if k >= last and x == "-f" and k + 1 < len(a):
            out += ["-max_interleave_delta", "0"]
        out.append(x)
    notes.append("max_interleave_delta 0")
    return out, "; ".join(notes)

args = sys.argv[1:]
try:
    args, note = fix(args)
    if note:
        with open(LOG, "a") as f:
            f.write(f"{time.strftime('%F %T')} {note}\n")
except Exception:          # never block playback
    args = sys.argv[1:]
os.execv(REAL, [REAL] + args)
```

Install (macOS):
```
cd /Applications/EmbyServer.app/Contents/MacOS
mv ffmpeg ffmpeg.emby && cp /path/to/wrapper.py ffmpeg && chmod 755 ffmpeg
```
(Revert with `mv ffmpeg.emby ffmpeg`. It has to be re-applied after each server update.)

With it, resume, seeking and subtitles all work with both `.mka` (AC3) and `.m4a` (AAC) sidecars on iOS, macOS and Web. One minor remaining glitch: when starting from 00:00 with subtitles on, the first ~4–5 seconds of the external track are missing.

Hardware transcoding (VideoToolbox) was not involved: our server transcodes in software.

Happy to provide full ffmpeg logs or test builds.

Posted

Hello Gu1llohm,

** This is an auto reply **

Please wait for someone from staff support or our members to reply to you.

It's recommended to provide more info, as it explain in this thread:


Thank you.

Emby Team

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...