Gu1llohm 0 Posted 2 hours ago Posted 2 hours ago **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.
Abobader 3543 Posted 2 hours ago Posted 2 hours ago 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now