<p>A shorter method is</p>

<pre><code>ffmpeg -i video.mp4 -vf 'select=eq(n,0)+between(n,310,930),setpts=if(eq(N,0),0,(N+260)/FRAME_RATE/TB)' -map [output] -vsync cfr -c:v libx264 -crf 18 -y output.mp4
</code></pre>

CC BY-SA 4.0
2019-04-01T17:03:44.860Z
It seems that this method also does not waste space encoding frames 1–260. Only frame 0 is encoded and the waiting is done by timestamp manipulation, which is neat.
Witiko
CC BY-SA 4.0
2019-03-31T04:38:04.120Z
2019-03-31T04:38:04.120Z
Gyan
<p>The <code>loop</code> filter produces the rest of the video after it has stopped looping. If this is undesirable, trim the resulting video as follows:</p>

<pre><code>$ ffmpeg -i video.mp4 -i video.mp4 -filter_complex '
    [0:v]loop=loop=259:size=1:start=0,trim=start_frame=0:end_frame=259[first-frame];
    [1:v]trim=start_frame=310:end_frame=930,setpts=PTS-STARTPTS[rest];
    [first-frame][rest]concat=n=2:v=1:a=0[output]
' -map [output] -c:v libx264 -crf 18 -y output.mp4
</code></pre>

<p>This behavior is perhaps counterintuitive and poorly documented, but it covers the common case, when one wants to loop at the beginning of a video. This behavior also makes <code>loop=0</code> an identity filter that passes the video unchanged.</p>

CC BY-SA 4.0
2019-03-31T04:42:33.373Z
The loop filter is meant to pass through untouched portions of the input while looping the specified portion. If it dropped the remainder, then the size and start are unnecessary and users would need to always manually trim and then concat the various segments, like your command does.
Gyan
CC BY-SA 4.0
2019-03-31T03:36:46.513Z
2019-03-31T04:00:39.670Z
2019-03-31T04:00:39.670Z
Witiko
<p>I would like to to play the first frame of an input video for 260 frames and then play frames 310–930 of the input video:</p>

<pre><code>$ ffmpeg -i video.mp4 -i video.mp4 -filter_complex '
    [0:v]loop=loop=259:size=1:start=0[first-frame];
    [1:v]trim=start_frame=310:end_frame=930,setpts=PTS-STARTPTS[rest];
    [first-frame][rest]concat=n=2:v=1:a=0[output]
' -map [output] -c:v libx264 -crf 18 -y output.mp4
</code></pre>

<p>The above command produces the first frame of the input video for 260 frames as expected, but then continues with frames 0-620 of the input video followed by frames 310–930 of the input video.</p>

<p>When I drop the <code>[first-frame]</code> part, frames 310–930 of the input video are correctly produced:</p>

<pre><code>$ ffmpeg -i video.mp4 -i video.mp4 -filter_complex '
    [1:v]trim=start_frame=310:end_frame=930,setpts=PTS-STARTPTS[rest];
    [rest]concat=n=1:v=1:a=0[output]
' -map [output] -c:v libx264 -crf 18 -y output.mp4
</code></pre>

<p>This is perhaps a timestamp problem, since the documentation for the <code>concat</code> filter clarifies that “for this filter to work correctly, all segments must start at timestamp 0.”</p>

<p>I am using the following version of ffmpeg:</p>

<pre><code>$ ffmpeg -version
ffmpeg version 3.2.12-1~deb9u1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: --prefix=/usr --extra-version='1~deb9u1' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libebur128 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
libavutil      55. 34.101 / 55. 34.101
libavcodec     57. 64.101 / 57. 64.101
libavformat    57. 56.101 / 57. 56.101
libavdevice    57.  1.100 / 57.  1.100
libavfilter     6. 65.100 /  6. 65.100
libavresample   3.  1.  0 /  3.  1.  0
libswscale      4.  2.100 /  4.  2.100
libswresample   2.  3.100 /  2.  3.100
libpostproc    54.  1.100 / 54.  1.100
</code></pre>

<ffmpeg>
Loop the first frame of a video and then play a selected portion of the video
Witiko
# Loop the first frame of a video and then play a selected portion of the video

(Asked by: username_0 on 2019-03-31)

I would like to to play the first frame of an input video for 260 frames and then play frames 310–930 of the input video:
$ ffmpeg -i video.mp4 -i video.mp4 -filter_complex '
    [0:v]loop=loop=259:size=1:start=0[first-frame];
    [1:v]trim=start_frame=310:end_frame=930,setpts=PTS-STARTPTS[rest];
    [first-frame][rest]concat=n=2:v=1:a=0[output]
' -map [output] -c:v libx264 -crf 18 -y output.mp4

The above command produces the first frame of the input video for 260 frames as expected, but then continues with frames 0-620 of the input video followed by frames 310–930 of the input video.
When I drop the [first-frame] part, frames 310–930 of the input video are correctly produced:
$ ffmpeg -i video.mp4 -i video.mp4 -filter_complex '
    [1:v]trim=start_frame=310:end_frame=930,setpts=PTS-STARTPTS[rest];
    [rest]concat=n=1:v=1:a=0[output]
' -map [output] -c:v libx264 -crf 18 -y output.mp4

This is perhaps a timestamp problem, since the documentation for the concat filter clarifies that “for this filter to work correctly, all segments must start at timestamp 0.”
I am using the following version of ffmpeg:
$ ffmpeg -version
ffmpeg version 3.2.12-1~deb9u1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: --prefix=/usr --extra-version='1~deb9u1' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libebur128 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
libavutil      55. 34.101 / 55. 34.101
libavcodec     57. 64.101 / 57. 64.101
libavformat    57. 56.101 / 57. 56.101
libavdevice    57.  1.100 / 57.  1.100
libavfilter     6. 65.100 /  6. 65.100
libavresample   3.  1.  0 /  3.  1.  0
libswscale      4.  2.100 /  4.  2.100
libswresample   2.  3.100 /  2.  3.100
libpostproc    54.  1.100 / 54.  1.100

**Tags:** ffmpeg


---

## 2 answers

### Answer by username_1 on 2019-03-31. Score: 2 | Accepted answer

A shorter method is
ffmpeg -i video.mp4 -vf 'select=eq(n,0)+between(n,310,930),setpts=if(eq(N,0),0,(N+260)/FRAME_RATE/TB)' -map [output] -vsync cfr -c:v libx264 -crf 18 -y output.mp4

> **Comments:**
> **username_0**: It seems that this method also does not waste space encoding frames 1–260. Only frame 0 is encoded and the waiting is done by timestamp manipulation, which is neat.  

---

### Answer by username_0 on 2019-03-31. Score: 1

The loop filter produces the rest of the video after it has stopped looping. If this is undesirable, trim the resulting video as follows:
$ ffmpeg -i video.mp4 -i video.mp4 -filter_complex '
    [0:v]loop=loop=259:size=1:start=0,trim=start_frame=0:end_frame=259[first-frame];
    [1:v]trim=start_frame=310:end_frame=930,setpts=PTS-STARTPTS[rest];
    [first-frame][rest]concat=n=2:v=1:a=0[output]
' -map [output] -c:v libx264 -crf 18 -y output.mp4

This behavior is perhaps counterintuitive and poorly documented, but it covers the common case, when one wants to loop at the beginning of a video. This behavior also makes loop=0 an identity filter that passes the video unchanged.

> **Comments:**
> **username_1**: The loop filter is meant to pass through untouched portions of the input while looping the specified portion. If it dropped the remainder, then the size and start are unnecessary and users would need to always manually trim and then concat the various segments, like your command does.  

---

