4

I have some sever-side code that currently supports the http byte range requests without an issue. However, I want to be able to transcode the video file (which is located on-disk) on-the-fly with ffmpeg before I send the transcoded chunk to the client, but ffmpeg requires I give it a seek time whereas I get byte ranges from the client. How would I be able to figure out the time range (seek time) of a video file given the byte range from the client browser?

I have already looked at this question which assumes the server already knows the specified time.

I am open to using an html5 video player which supports the use of time ranges to request data instead of byte ranges, but I have been unable to find an implementation or figure out how the javascript side of buffering <video> works.

Community
  • 1
  • 1
fengshaun
  • 2,100
  • 1
  • 16
  • 25
  • You can try [fetching](https://ffmpeg.org/ffmpeg-protocols.html#http) the video with `offset` and `end_offset` – Gyan Mar 15 '17 at 06:03
  • Those options seem to be only for http streaming directly with ffmpeg. I'm using ffmpeg to transcode only. – fengshaun Mar 15 '17 at 06:24
  • The commit which added those mention "request ranges". – Gyan Mar 15 '17 at 06:27
  • Do you have a link to the commit? thanks. – fengshaun Mar 15 '17 at 06:38
  • https://github.com/FFmpeg/FFmpeg/commit/2ec33d27127251bbc45e1f88e60691ad59cf2319 – Gyan Mar 15 '17 at 06:41
  • `$ ffmpeg -i 1.mp4 -acodec copy -vcodec copy -offset -end_offset 2.mp4` gives back the entire video file unchanged, starting transcoding from the beginning to the end. The commit checks for and adds the `Range` header, which again tells me these options deal with ffmpeg's http output and not local file input/output. – fengshaun Mar 15 '17 at 09:20
  • Of course it does not deal with local file input. The commit applies to the http protocol, so the syntax is `ffmpeg -offset START -end_offset END -i http://source-url -c copy out.mp4` BTW, your command copies and doesn't transcode, so you may lose some frames at start. – Gyan Mar 15 '17 at 09:29
  • The file I'm trying to transcode is located on-disk. I've updated the question wording to make that clearer. – fengshaun Mar 15 '17 at 09:35

1 Answers1

6

You can run ffprobe and analyze its output to identify the timestamps.

Basic command is

ffprobe -i in.mp4 -show_entries packet=pos,pts_time,flags -select_streams v -of compact=p=0:nk=1 -v 0

This produces

0.000000|48|K_
0.133333|956|__
0.066667|996|__
0.033333|1053|__
0.100000|1602|__
0.266667|1811|__
0.200000|2371|__
0.166667|2746|__
0.233333|3294|__
....

The first column is the video frame timestamp, the 2nd is the byte offset for that frame and the 3rd is whether the frame is a keyframe.

Since you can only cut video at keyframes, when copying the stream, you will either have to cut at a timestamp whose flag is K or use the argument in the command below:

ffmpeg -ss X -i in.mp4 -c copy -avoid_negative_ts make_zero out.mp4

This is not needed if you're transcoding the video stream.

Gyan
  • 85,394
  • 9
  • 169
  • 201