Closed m1k1o closed 1 year ago
From https://man.archlinux.org/man/extra/ffmpeg/ffmpeg-all.1.en#time
If the argument consists of timestamps, ffmpeg will round the specified times to the nearest output timestamp as per the encoder time base and force a keyframe at the first frame having timestamp equal or greater than the computed timestamp
Current philisophy is, that we separate whole recording to discrete segments, and everytime that segment is requested we transcode it. Segments must be created at keyframes, but ffmpeg is rounding specified times and sometimes splitting them unexpectedly.
I spent a lot of time trying to fix this before giving up to create go-vod (it doesn't create separate ffmpeg processes, instead just sends a SIGSTOP to pause transcoding). The problem is this:
Say all segments are 3s in length, and I've a segment starting at t=6s. Then the segment might end at t=9s. When we try to create the next segment starting at t=9s, then ffmpeg starts it at some keyframe say t=9.1s. That means 100ms of video disappeared, which leads to weird playback bugs. It might be even worse -- the keyframe at which it ends may be before 9s. And there's nothing we can do about the approximations.
@pulsejet but that is optimized only for a single user, right? Correct me if I am worong, but the segments are not predictable; depending on where you started the playback their timing might be different. Therefore they cannot be cached and reused when two client would start watching at different time (example: second would be 5 min ahead of first one).
In that case, you are sending SIGSTOP
to stop transcoding too many segments, right? In that case maybe adding -re
without SIGSTOP
would yield the same results, but the CPU load would be distributed and not in peaks (only when transcoding).
@pulsejet but that is optimized only for a single user, right? Correct me if I am worong, but the segments are not predictable; depending on where you started the playback their timing might be different. Therefore they cannot be cached and reused when two client would start watching at different time (example: second would be 5 min ahead of first one).
Correct, there cannot be any caching since the start time must align if the user skips ahead. We can cache for the case where users don't skip, though, which might be the case for certain types of content.
In that case, you are sending
SIGSTOP
to stop transcoding too many segments, right? In that case maybe adding-re
withoutSIGSTOP
would yield the same results, but the CPU load would be distributed and not in peaks (only when transcoding).
The browser buffers ahead, so I'm not sure if/how -re
would allow that.
Ignoring unexpected segments (https://github.com/m1k1o/go-transcode/commit/e3c42330ad6c06d4cc7c6542e409cf445ea05498) from ffmpeg seem to fix this issue. Those segments were typically very short in comparsion to expected segment length (200ms vs 4sec) and therefore significant amount of video playback was lost. By ignoring them we might still loose some slice of the media, because last segment is shorter than expected. But on the other side, the same rounding that was applied to last segment could be applied to the first segment in the the next trancsoding job and therefore compensate for the loss.
Given we have a test video and want to force keframes at
1772,1776
timestamps:Response shows us:
What is not what we expected. We expected to see
1772
and1776
in the output.