options: add --sub-pause to pause on each subtitle's last frame - #18408
options: add --sub-pause to pause on each subtitle's last frame#18408feldgendler wants to merge 1 commit into
Conversation
Pauses playback on the last video frame on which each primary subtitle is still visible. Resuming plays to the end of the next subtitle, so repeated resuming steps through dialogue line by line. Finding that frame means comparing the frame being displayed against the one about to be queued, which is only possible in write_video(). The pause is placed after the frame stepping block so that a frame step gets to clear step_frames and unmute first. sub_ends_between() compares in the subtitle timebase, so --sub-delay and --sub-speed are accounted for. This adds a get_times() call per displayed frame while the option is enabled. Also saved in watch later files, like the other sub-* options. Tested with SRT and embedded ASS, and with --sub-delay and --sub-speed set both ways.
|
is there any scenario where the following profile fails?
It may be worth discussing whether sub-start and sub-end should account for sub-delay by default or not, I'm not sure such a niche option is worth adding. Especially one that's 3 lines with auto profiles |
A few scenarios:
Here is a steel-man version that addresses the first three: mpv.conf input.conf The 1.5/fps formula replaces the fixed window (1/fps can be too little e.g. with PGS). As for frame-dropping, I haven't figured out how to fix it. If the last frame with the subtitle visible gets dropped, my sub-pause code adapts and pauses on the preceding frame that is actually shown, but the profile condition doesn't. Widening the window trades precision for reliability. So the two narrowly surviving reasons to take this PR are:
I understand if these don't clear the bar. Thanks for considering it, anyway. |
Pauses playback on the last video frame on which each primary subtitle is still visible. Resuming plays to the end of the next subtitle, so repeated resuming steps through dialogue line by line. Off by default.
This is meant for language learners, who want to stop on each line long enough to read it, look a word up, or replay the audio. Pausing by hand always lands after the line has left the screen, so it has to be recalled rather than read, and pausing on a timer drifts as soon as the dialogue does.
It has been written as a user script several times, but those are all subtly wrong when --sub-delay is set: sub_get_times() returns subtitle-timebase values and pts_to_subtitle() is static in dec_sub.c, so a pause point computed from the sub-end property is off by exactly the delay. A script also only learns about the transition after the line is already gone. sub_ends_between() compares in the subtitle timebase, so --sub-delay and --sub-speed are accounted for.
The manual lists the cases where this does nothing, mostly for want of a following frame to pause on: audio-only playback, cover art, the last frame of a file, --untimed and --video-latency-hacks. It also does nothing for subtitles with unknown end times and for subrandr, which has no get_times, and with ASS it stops on signs too, since get_times() covers every event at that PTS.
Tested with SRT and embedded ASS, with --sub-delay both ways and --sub-speed at 0.5 and 2, and with subtitles hidden, disabled, and during backward playback.
Written with AI assistance, and reviewed with AI tooling. I take full responsibility for the code: I understand what it changes and why, I have tested it myself, I will respond to review in my own words, and it can be submitted under the same license as the files it touches.