Walter_Ego 2 Posted Sunday at 11:21 PM Posted Sunday at 11:21 PM hi team, i spent some time looking into why my emby server sometimes leaves ffmpeg processes pegging 100% of a core post-playback, and i figured out why and how to fix it (it's already fixed upstream). it seems that this occurs when ffmpeg seeks beyond the start of the last cue of the subtitle track. if a video is 1 minute long, but the subtitles end 30 seconds in, and you seek to 31 seconds, this will cause the process to remain, and spin its wheels. in fact, it occurs on any filtered subtitle output that receives zero frames; i reproduced it with a sparse forced track and a seek to a point in the first half of a video. looking at https://mediabrowser.github.io/embytools/ffmpeg-2023_06_25-u1.tar.gz i can see that this is due to the emby patches on top of ffmpeg. in fftools/ffmpeg_filter.c:758 is this comment: if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE && ist->dec_ctx) { // For subtitles, we need to set the format here. Would we leave the format // at -1, it would delay processing (ifilter_has_all_input_formats()) until // the first subtile frame arrives, which could never happen in the worst case ifilter->format = (uint16_t)ist->dec_ctx->subtitle_type; } so emby presets the format so a subtitle graph configures with zero frames, which breaks the invariant that early return was written against - af1761f7b5 - "init filtergraphs only after we have a frame on each input". this means choose_output() can select this output stream that is already finished as is seen in fftools/ffmpeg.c:3855: static OutputStream *choose_output(void) { for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; ... if (!ost->initialized && !ost->inputs_done) return ost->unavailable ? NULL : ost; if (!ost->finished && opts < opts_min) { opts_min = opts; ost_min = ost->unavailable ? NULL : ost; } } return ost_min; } inputs_done is never set for a configured graph, and a subtitle sink with zero frames never sets initialized either. both flags stay 0 permanently so choose_output()'s early return fires forever, resulting in a livelock. emby tries to send "q" to ffmpeg's stdin to gracefully shut it down, but it never acts on it due to the livelock, so the process just spins its wheels forever. the fix is to extend the test for the return: if (!ost->initialized && !ost->inputs_done && !ost->finished) this is probably best done by cherry picking e1d12aaa45 onto the 5.1-emby source you could also harden this in reap_filters() in fftools/ffmpeg.c:1522: } else if (flush && ret == AVERROR_EOF) { if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) do_video_out(of, ost, NULL); else init_output_stream_wrapper(ost, NULL, 1); } that's pretty much the whole story. i see that there are other posts likely about this as well. also, i can't seem to find the p6 version source for ffmpeg, could you please point me towards it?
Walter_Ego 2 Posted yesterday at 01:05 AM Author Posted yesterday at 01:05 AM g'day, just wondering if this was seen, @Luke? it is a trivially reproducible bug, and the two fixes described work individually and together, and create identical output to the current code. all you should need to do is seek past the end of a subtitle track while transcoding, since its an ffmpeg issue. you can cause it easily enough on the cli without operating emby too. i can provide test artifacts and exact commands if required.
Luke 42813 Posted yesterday at 02:58 AM Posted yesterday at 02:58 AM Hi, yes we can look at this as part of the new ffmpeg build that will be on the server beta channel soon. Thanks. @softworkz 1
softworkz 5315 Posted 13 hours ago Posted 13 hours ago @Walter_Ego - thanks a lot for the detailed report. Could you please provide a test file and a command line which reproduces this? I have sent you an upload link. I want to test it against our new FFmpeg, where these things have fundamentally changed. On 7/27/2026 at 1:21 AM, Walter_Ego said: also, i can't seem to find the p6 version source for ffmpeg, could you please point me towards it? There was no code change in this version. The only change was adding --disable-decoder=magicyuv for building. 1
Walter_Ego 2 Posted 10 hours ago Author Posted 10 hours ago @softworkzdone. comment was longer than the form view so just repasting here: this is just a short mkv file with a subrip stream, last cue starts at 27 seconds, seeking anywhere after the start of the last cue should cause the livelock behavior. same behavior should occur with any subtitle stream being streamed with any video file. there is nothing special about this file. pop it in a directory, then run: docker run --rm -v "$PWD":/work:ro --entrypoint /bin/ffmpeg emby/embyserver:beta -hide_banner -loglevel error -y -copyts -start_at_zero -ss 45 -i /work/in.mkv -filter_complex '[0:v]scale=320:240[v]' -map '[v]' -map 0:a -sn -c:v mpeg2video -q:v 8 -c:a copy -f segment -segment_format mpegts -segment_time 3 -segment_start_number 15 -individual_header_trailer 0 /tmp/seg_%d.ts -map 0:s -an -vn -c:s webvtt -f segment -segment_format webvtt -segment_time 3 -segment_start_number 15 -write_empty_segments 1 -break_non_keyframes 1 -individual_header_trailer 1 /tmp/sub_%d.vtt
Walter_Ego 2 Posted 10 hours ago Author Posted 10 hours ago if your new ffmpeg is 6.1+ the issue would already be resolved btw 1
softworkz 5315 Posted 6 hours ago Posted 6 hours ago Thanks a lot for the sample file and the command. I was able to reproduce it with the current FFmpeg - even though it was still reacting to input - i.e. pressing q caused it to exit (tested on Windows) The new FFmpeg (8.x based) doesn't expose this 3 hours ago, Walter_Ego said: if your new ffmpeg is 6.1+ the issue would already be resolved btw I was a bit confused because stock ffmppeg doesn't have this behavior (because they have no subtitle filtering), so I wanted dto be sure. Thanks a lot for reporting!
Walter_Ego 2 Posted 54 minutes ago Author Posted 54 minutes ago (edited) im not at a computer right now, but i believe if you seek to near the end of the file and wait for playback to fully complete, q will not cause it to exit. i believe once the cpu pegging occurs the and there is nothing further to transcode at all the non-responsive state of the issue is exposed. i think i wrongly described it as a livelock at the point the cpu pegging occurs, i think there must also be no streams left to transcode. will reconfirm when i get to a computer in a few hours. Edited 50 minutes ago by Walter_Ego
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