Answers.Body: <p>Transport Stream files are meant for streaming, have no global header, and may be sliced or joined together without the help of a format-aware utility. Because of this, there'a a lot of metadata structure within a TS file that allows them to be playable even after such operations. What that allows, in turn, is having multiple streams of different duration starting and stopping at different times. A format-aware utility like ffmpeg will parse the metadata and respect these features whereas a video editor which is mainly designed for a static file-based and indexed media usually won't - not with full fidelity anyway.</p>
  
  <p>In the sample, there are two streams - 1 video and 1 audio. Run the following to identify the start_time of each stream</p>
  
  <pre><code>ffprobe -show_entries stream=codec_type,start_time -v 0 -of compact=p=1:nk=0 sample.ts
  </code></pre>
  
  <p>For your file, this results in</p>
  
  <pre><code>program|stream|codec_type=video|start_time=1.978233
  stream|codec_type=audio|start_time=1.400000
  
  stream|codec_type=video|start_time=1.978233
  stream|codec_type=audio|start_time=1.400000
  </code></pre>
  
  <p>Ignore the first two lines. You can see that the video start is delayed relative to the audio. FFmpeg respects this delay. Your editor likely doesn't. It will either ignore the surplus audio or desync it with respect to the video.</p>
  
  <p>So, <code>00:00:34.600</code> in the editing timeline actually references absolute timestamp of <code>34.6 + 1.978233 = 36.578233</code>.</p>
  
  <p>So, to accurately extract the desired frame, you need to know the delay of the video stream. Now, ffmpeg, by default, removes the starting offset i.e. it subtracts the start_time of the earliest starting stream before ingesting into its processing pipeline (unless copyts is set).</p>
  
  <p>So, without copyts, the video start_time will be modified to <code>1.978233 - 1.400000 = 0.578233</code> and the desired frame will be at <code>34.6 + 0.578233 = 35.178233</code>.</p>
  
  <p>So, run</p>
  
  <pre><code>ffmpeg -i sample.ts -ss 00:00:35.178233 -t 00:26:40.400 [commands] out.mp4
  </code></pre>
  
  <p>You can use</p>
  
  <pre><code>ffprobe -show_entries format=start_time:stream=start_time -select_streams v -v 0 -of compact=p=1:nk=0 sample.ts
  </code></pre>
  
  <p>to get</p>
  
  <pre><code>program|stream|start_time=1.978233
  
  stream|start_time=1.978233
  format|start_time=1.400000
  </code></pre>
  
  <p>where the relative offset for the video is <code>1.978233 - 1.400000 = 0.578233</code></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-11-29T06:04:42.863Z
Answers.LastActivityDate: 2018-11-29T06:04:42.863Z
Answers.UserDisplayName: Gyan
Body: <p>To put this plainly, <code>-ss</code> and <code>-t</code> don't work very well or even consistently.</p>
  
  <p>I'm trying to take a single input file<sup>1</sup> and only encode from a certain start point, <code>-ss</code>, and for only a certain time, <code>-t</code>. I've checked and double checked my in times are what I want, down to the frame (calculated to milliseconds<sup>2</sup>), but ffmpeg adds anywhere from 10 to 19 frames to the beginning, which is more than a half a second. I need frame precise cuts at the in points. Out points can be off by a few if necessary.</p>
  
  <p>I've run the following commands all with exactly the same results on 13 different files. All add the 10 to 19 frames to the beginning.</p>
  
  <pre><code>ffmpeg -ss 00:00:34.600 -t 00:26:40.400 -i 002.m2t [commands] 01.mp4
  ffmpeg -i 002.m2t -ss 00:00:34.600 -t 00:26:40.400 [commands] 01.mp4
  ffmpeg -ss 00:00:34.600 -i 002.m2t -t 00:26:40.400 [commands] 01.mp4
  </code></pre>
  
  <p>The [commands] section is exactly</p>
  
  <pre><code>-filter_complex "scale=852:480,setsar=1","eq=brightness=0.05:saturation=1.0" -crf 24 -c:a aac -b:a 64k -ac 1 -loglevel quiet -stats -movflags +faststart
  </code></pre>
  
  <p>I find many with the same issue, but no solutions. I thought at first that putting <code>-ss</code> and <code>-t</code> before <code>-i</code> would work, but as you can see I've tried moving them around and get exactly the same results.</p>
  
  <p>Is there really no way to cut a video with frame precision in ffmpeg?</p>
  
  <hr>
  
  <p>In the documentation I found <code>-seek_timestamp</code> which says</p>
  
  <blockquote>
    <p>This option enables or disables seeking by timestamp in input files with the -ss option. It is disabled by default. If enabled, the argument to the -ss option is considered an actual timestamp, and is not offset by the start time of the file. This matters only for files which do not start from timestamp 0, such as transport streams.</p>
  </blockquote>
  
  <p>I know m2t (see footnote 1) is a transport stream, so I tried using <code>-seek_timestamp</code>, but I get errors that seem to be about parsing the arguments. I've tried putting it in different places in the command too. Maybe the answer is here, but I'm having trouble with the syntax.</p>
  
  <hr>
  
  <p>Footnotes</p>
  
  <ol>
  <li><p>The input files are MT2 HDV recorded via firewire from an old Sony cam direct to Vegas Pro.</p></li>
  <li><p>I import the files to Vegas Pro and trim them on the timeline like any other edit job, but instead of rendering in Vegas Pro, I export the events to eventually derive the ffmpeg commands, with <code>-ss</code> and <code>-t</code> effectively pulled directly from the Vegas Pro timeline. When I do this, the <code>-ss 00:00:34.600</code> in the command above  actually came from the Vegas Pro events like this: <code>00:00:34;18</code>. The 18 at the end is 18 <em>frames</em>. Since this is 30 fps footage, I calculate the milliseconds needed for the ffmpeg command by dividing by 30. <code>18/30 = .6</code>.</p></li>
  </ol>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-24T05:08:18.413Z
Comments.Text: For TS files, `ss` should come after the file name. `ss` before `-i` relies on a global index in the container which TS files don't have. TS files timestamps also can be a bit offset since there's a delay often added to allow the streaming receiver to get initialized properly. Can you share a small sample of this input? `ffmpeg -i 002.m2t -copyts -c copy -t 50 sample.ts` and also an image of the expected frame for `00:00:34.600`
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-25T19:15:56.360Z
Comments.Text: @Gyan Thanks for waiting. Here's [the expected frame for `00:00:34.600`](https://www.dropbox.com/s/wggy3rps1b8iecv/34_6-snap.jpg) and [the copied first 50 seconds.](https://www.dropbox.com/s/lq6gwqj5utvcrvf/sample.ts) I had to run the copy command without `-copyts` but verified that they are identical and can reproduce the issue on sample.ts when converting it to mp4.
Comments.UserDisplayName: user3643
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-26T05:47:29.880Z
Comments.Text: Why did `copyts` fail?
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-26T06:11:12.667Z
Comments.Text: @gyan Not sure. Don't remember.
Comments.UserDisplayName: user3643
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-28T03:57:45.280Z
Comments.Text: @Gyan Did you find anything? Could you reproduce the issue on the sample file?
Comments.UserDisplayName: user3643
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-28T05:12:46.053Z
Comments.Text: I'll look at it today.
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-28T18:32:01.090Z
Comments.Text: I had a look. Slightly involved, so I'll post an answer in the morning.
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-11-28T23:50:38.810Z
Comments.Text: @Gyan Wow, I didn't think it would be such an issue. If you get something that works, there's a 100 rep bounty in it for you.
Comments.UserDisplayName: user3643
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-05-11T22:24:39.337Z
Comments.Text: Related: [Why are there missing frames in the Vegas Pro editing timeline?](https://video.stackexchange.com/q/27601/3643)
Comments.UserDisplayName: user3643
Tags: <ffmpeg>
Title: How to precisely trim video with ffmpeg? -ss and -t are off by more than a half second
UserDisplayName: user3643
ThreadText: # How to precisely trim video with ffmpeg? -ss and -t are off by more than a half second
  
  (Asked by: username_0 on 2018-11-23)
  
  To put this plainly, `-ss` and `-t` don't work very well or even consistently.
  
  I'm trying to take a single input file1 and only encode from a certain start point, `-ss`, and for only a certain time, `-t`. I've checked and double checked my in times are what I want, down to the frame (calculated to milliseconds2), but ffmpeg adds anywhere from 10 to 19 frames to the beginning, which is more than a half a second. I need frame precise cuts at the in points. Out points can be off by a few if necessary.
  
  I've run the following commands all with exactly the same results on 13 different files. All add the 10 to 19 frames to the beginning.
  
  ```
  ffmpeg -ss 00:00:34.600 -t 00:26:40.400 -i 002.m2t [commands] 01.mp4
  ffmpeg -i 002.m2t -ss 00:00:34.600 -t 00:26:40.400 [commands] 01.mp4
  ffmpeg -ss 00:00:34.600 -i 002.m2t -t 00:26:40.400 [commands] 01.mp4
  
  ```
  
  The [commands] section is exactly
  
  ```
  -filter_complex "scale=852:480,setsar=1","eq=brightness=0.05:saturation=1.0" -crf 24 -c:a aac -b:a 64k -ac 1 -loglevel quiet -stats -movflags +faststart
  
  ```
  
  I find many with the same issue, but no solutions. I thought at first that putting `-ss` and `-t` before `-i` would work, but as you can see I've tried moving them around and get exactly the same results.
  
  Is there really no way to cut a video with frame precision in ffmpeg?
  
  ---
  
  In the documentation I found `-seek_timestamp` which says
  
  > This option enables or disables seeking by timestamp in input files with the -ss option. It is disabled by default. If enabled, the argument to the -ss option is considered an actual timestamp, and is not offset by the start time of the file. This matters only for files which do not start from timestamp 0, such as transport streams.
  
  I know m2t (see footnote 1) is a transport stream, so I tried using `-seek_timestamp`, but I get errors that seem to be about parsing the arguments. I've tried putting it in different places in the command too. Maybe the answer is here, but I'm having trouble with the syntax.
  
  ---
  
  Footnotes
  
  1. The input files are MT2 HDV recorded via firewire from an old Sony cam direct to Vegas Pro.
  2. I import the files to Vegas Pro and trim them on the timeline like any other edit job, but instead of rendering in Vegas Pro, I export the events to eventually derive the ffmpeg commands, with `-ss` and `-t` effectively pulled directly from the Vegas Pro timeline. When I do this, the `-ss 00:00:34.600` in the command above actually came from the Vegas Pro events like this: `00:00:34;18`. The 18 at the end is 18 *frames*. Since this is 30 fps footage, I calculate the milliseconds needed for the ffmpeg command by dividing by 30. `18/30 = .6`.
  
  **Tags:** ffmpeg
  
  > **Comments:**
  > **username_1**: For TS files, `ss` should come after the file name. `ss` before `-i` relies on a global index in the container which TS files don't have. TS files timestamps also can be a bit offset since there's a delay often added to allow the streaming receiver to get initialized properly. Can you share a small sample of this input? `ffmpeg -i 002.m2t -copyts -c copy -t 50 sample.ts` and also an image of the expected frame for `00:00:34.600`  
  > **username_0**: @username_1 Thanks for waiting. Here's [the expected frame for `00:00:34.600`](https://www.dropbox.com/s/wggy3rps1b8iecv/34_6-snap.jpg) and [the copied first 50 seconds.](https://www.dropbox.com/s/lq6gwqj5utvcrvf/sample.ts) I had to run the copy command without `-copyts` but verified that they are identical and can reproduce the issue on sample.ts when converting it to mp4.  
  > **username_1**: Why did `copyts` fail?  
  > **username_0**: @username_1 Not sure. Don't remember.  
  > **username_0**: @username_1 Did you find anything? Could you reproduce the issue on the sample file?  
  > **username_1**: I'll look at it today.  
  > **username_1**: I had a look. Slightly involved, so I'll post an answer in the morning.  
  > **username_0**: @username_1 Wow, I didn't think it would be such an issue. If you get something that works, there's a 100 rep bounty in it for you.  
  > **username_0**: Related: [Why are there missing frames in the Vegas Pro editing timeline?](https://video.stackexchange.com/q/27601/3643)  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2018-11-29. Score: 10
  
  Transport Stream files are meant for streaming, have no global header, and may be sliced or joined together without the help of a format-aware utility. Because of this, there'a a lot of metadata structure within a TS file that allows them to be playable even after such operations. What that allows, in turn, is having multiple streams of different duration starting and stopping at different times. A format-aware utility like ffmpeg will parse the metadata and respect these features whereas a video editor which is mainly designed for a static file-based and indexed media usually won't - not with full fidelity anyway.
  
  In the sample, there are two streams - 1 video and 1 audio. Run the following to identify the start\_time of each stream
  
  ```
  ffprobe -show_entries stream=codec_type,start_time -v 0 -of compact=p=1:nk=0 sample.ts
  
  ```
  
  For your file, this results in
  
  ```
  program|stream|codec_type=video|start_time=1.978233
  stream|codec_type=audio|start_time=1.400000
  
  stream|codec_type=video|start_time=1.978233
  stream|codec_type=audio|start_time=1.400000
  
  ```
  
  Ignore the first two lines. You can see that the video start is delayed relative to the audio. FFmpeg respects this delay. Your editor likely doesn't. It will either ignore the surplus audio or desync it with respect to the video.
  
  So, `00:00:34.600` in the editing timeline actually references absolute timestamp of `34.6 + 1.978233 = 36.578233`.
  
  So, to accurately extract the desired frame, you need to know the delay of the video stream. Now, ffmpeg, by default, removes the starting offset i.e. it subtracts the start\_time of the earliest starting stream before ingesting into its processing pipeline (unless copyts is set).
  
  So, without copyts, the video start\_time will be modified to `1.978233 - 1.400000 = 0.578233` and the desired frame will be at `34.6 + 0.578233 = 35.178233`.
  
  So, run
  
  ```
  ffmpeg -i sample.ts -ss 00:00:35.178233 -t 00:26:40.400 [commands] out.mp4
  
  ```
  
  You can use
  
  ```
  ffprobe -show_entries format=start_time:stream=start_time -select_streams v -v 0 -of compact=p=1:nk=0 sample.ts
  
  ```
  
  to get
  
  ```
  program|stream|start_time=1.978233
  
  stream|start_time=1.978233
  format|start_time=1.400000
  
  ```
  
  where the relative offset for the video is `1.978233 - 1.400000 = 0.578233`
  
  
  ---
  
  