Answers.Body: <p>I've put together a Python script that will do all of this.
  Generates the <code>ffprobe</code> and <code>ffmpeg</code> commands and runs them And outputs a file without black clips</p>
  <p>GitHub repo: <a href="https://github.com/FarisHijazi/deblack" rel="nofollow noreferrer">https://github.com/FarisHijazi/deblack</a></p>
  <p>GitHub gist (archived): <a href="https://gist.github.com/FarisHijazi/eff7a7979440faa84a63657e085ec504" rel="nofollow noreferrer">https://gist.github.com/FarisHijazi/eff7a7979440faa84a63657e085ec504</a></p>
  <pre class="lang-python prettyprint-override"><code>&quot;&quot;&quot;
  @author: https://github.com/FarisHijazi
  Use ffprobe to extract black frames and ffmpeg to trim them and output a new video
  &quot;&quot;&quot;
  
  # help from:
  # https://video.stackexchange.com/questions/16564/how-to-trim-out-black-frames-with-ffmpeg-on-windows#new-answer?newreg=d534934be5774bd1938b535cd76608cd
  # https://github.com/kkroening/ffmpeg-python/issues/184#issuecomment-493847192
  
  
  import argparse
  import os
  import shlex
  import subprocess
  
  parser = argparse.ArgumentParser(__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  parser.add_argument('input', type=str, help='input video file')
  parser.add_argument('--invert', action='store_true', help='remove nonblack instead of removing black')
  args = parser.parse_args()
  
  ##FIXME: sadly you must chdir so that the ffprobe command will work
  os.chdir(os.path.split(args.input)[0])
  args.input = os.path.split(args.input)[1]
  
  spl = args.input.split('.')
  outpath = '.'.join(spl[:-1]) + '.' + ('invert' if args.invert else '') + 'out.' + spl[-1]
  
  
  def delete_back2back(l):
    from itertools import groupby
    return [x[0] for x in groupby(l)]
  
  
  def construct_ffmpeg_trim_cmd(timepairs, inpath, outpath):
    cmd = f'ffmpeg -i &quot;{inpath}&quot; -y -filter_complex '
    cmd += '&quot;'
    for i, (start, end) in enumerate(timepairs):
      cmd += (f&quot;[0:v]trim=start={start}:end={end},setpts=PTS-STARTPTS,format=yuv420p[{i}v]; &quot; +
              f&quot;[0:a]atrim=start={start}:end={end},asetpts=PTS-STARTPTS[{i}a]; &quot;)
    for i, (start, end) in enumerate(timepairs):
      cmd += f&quot;[{i}v][{i}a]&quot;
    cmd += f'concat=n={len(timepairs)}:v=1:a=1[outv][outa]'
    cmd += '&quot;'
    cmd += f' -map [outv] -map [outa] &quot;{outpath}&quot;'
    return cmd
  
  
  def get_blackdetect(inpath, invert=False):
    ffprobe_cmd = f&quot;ffprobe -f lavfi -i \&quot;movie={inpath},blackdetect[out0]\&quot; -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet&quot;
    print('ffprobe_cmd:', ffprobe_cmd)
    lines = subprocess.check_output(shlex.split(ffprobe_cmd)).decode('utf-8').split('\n')
    times = [float(x.split('=')[1].strip()) for x in delete_back2back(lines) if x]
    assert len(times), 'no black detected'
  
    if not invert:
      times = [0] + times[:-1]
    timepairs = [(times[i], times[i + 1]) for i in range(0, len(times) // 2, 2)]
    return timepairs
  
  
  timepairs = get_blackdetect(args.input, invert=args.invert)
  cmd = construct_ffmpeg_trim_cmd(timepairs, args.input, outpath)
  
  print(cmd)
  os.system(cmd)
  
  </code></pre>
  <p>Combining multiple answers together:</p>
  <ul>
  <li><a href="https://video.stackexchange.com/a/16571/37220">https://video.stackexchange.com/a/16571/37220</a></li>
  <li><a href="https://superuser.com/a/1498811/739491">https://superuser.com/a/1498811/739491</a></li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-01-05T18:37:32.903Z
Answers.LastActivityDate: 2022-10-19T18:08:45.650Z
Answers.LastEditDate: 2022-10-19T18:08:45.650Z
Answers.UserDisplayName: FarisHijazi
Answers.Body: <p>Here's a way to do it with the <code>blackdetect</code> and <code>trim</code> filters.</p>
  
  <p>First, a better way to get the <code>blackdetect</code> output is via <code>ffprobe</code> because it is capable of writing structured data such as <code>XML</code>, <code>JSON</code> or one <code>key=value</code> per line. </p>
  
  <p>You do this using metadata injection:</p>
  
  <p><code>ffprobe -f lavfi -i "movie=/path/to/input.mp4,blackdetect[out0]" -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet
  TAG:lavfi.black_start=0
  TAG:lavfi.black_end=5.42208
  TAG:lavfi.black_start=73.4067
  </code></p>
  
  <p>As you can see it returns the start and end time of each black section. You use the returned info to <code>trim</code> the segments between each <code>end</code> and the next <code>start</code>:</p>
  
  <p><code>ffmpeg -i /path/to/input.mp4 -filter_complex "[0:v]trim=start=5.42208:end=73.4067,setpts=PTS-STARTPTS[v1];[0:a]atrim=start=5.42208:end=73.4067,asetpts=PTS-STARTPTS[a1]" -map [v1] -map [a1] output.mp4</code></p>
  
  <p>You can chain multiple <code>trim</code> filters in the same command. See <a href="https://superuser.com/questions/681885/how-can-i-remove-multiple-segments-from-a-video-using-ffmpeg">this answer</a> for a detailed example.</p>
  
  <p>To automate this in Windows you can install and use <a href="https://en.wikipedia.org/wiki/Windows_PowerShell" rel="noreferrer">PowerShell</a> or another scripting language of your choice (PHP, Python etc).</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T13:22:09.613Z
Answers.Text: Your help is appreciated, and seems to be the right path.  However I tried the ffprobe command you suggested:
  `ffprobe -f lavfi -i "movie=2013-10-14_14-30-55.mov,blackdetect[out0]" -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet` But no entries come out at all. Could this be, because the frames in question are not black enough, or am I doing it wrong?  I don't understand some of the commands.
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T13:43:29.170Z
Answers.Text: @RobertKoernke I used the default `blackdetect` settings, check its arguments and example on https://ffmpeg.org/ffmpeg-filters.html#blackdetect. Make sure you also have a recent version of `ffmpeg` and not a default distro installation.
Answers.UserDisplayName: aergistal
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T13:46:01.347Z
Answers.Text: The command means: do `blackdetect`, show only `black_start` and `black_end` tags, use the default output format  `-of default` with no wrappers `nw=1` and suppress all other output `-v quiet`
Answers.UserDisplayName: aergistal
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T17:41:10.553Z
Answers.Text: btw... You are giving me Windows instructions correct? Ok I temporarily took off the `-v quiet` and I get this:
  [Parsed_movie_0 @ 0056f560] Failed to avformat_open_input 'C'
  [lavfi @ 0056e2a0] Error initializing filter 'movie' with args 'C:UsersDOCUME~12013-10-14_14-30-55.mov'
  movie=C:\Users\DOCUME~1\2013-10-14_14-30-55.mov,blackdetect=d=0:pix_th=51.80[out0]: No such file or directory`
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T17:46:13.740Z
Answers.Text: The `-v quiet` was suppressing the error messages.
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T17:50:11.013Z
Answers.Text: I got it... I put the video in the same directory and ran it, and it is working.  So I'll keep testing..Thankx
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T18:18:26.223Z
Answers.Text: I've tried many different items in my tests.  Many times I'll get 'file not found' when clearly the file is there.  As I've shows I've tried old dos file types.  What is causing the issue here:
  "movie=C:\Users\INSPIR~1\DOCUME~1\a2d2\A2D2DE~1\MAC_SP~1.com\videos\2013-10-14_14-30-55.mov,blackdetect[out0]"
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-09T07:42:45.053Z
Answers.Text: When you use a path inside a command argument you have to escape the special characters or quote it, or use shorter, simple paths. https://ffmpeg.org/ffmpeg-utils.html#toc-Quoting-and-escaping
Answers.UserDisplayName: aergistal
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-12T12:46:31.077Z
Answers.Text: No escaping \\..\\ seems to work.. It continues to show the error: 
  `Error initializing filter 'movie' with args` - The alternative is that I'm going to use is to copy to the local ffprobe/ffmpeg directory as a temp file, process it there, and then move the processed version where I need it.  Thanx.
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-18T22:55:29.600Z
Answers.Text: Finally figured out the escaping here.  I finally needed it:
  "movie=\'C:\\Users\\Inspiron 560\\Documents\\temp.wmv\',blackdetect[out0]" Like so... The help page linked above was vague and did not show the way for ffprobe-movie.
Answers.UserDisplayName: Robert Koernke
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-08T09:02:32.360Z
Answers.LastActivityDate: 2015-10-08T09:02:32.360Z
Answers.LastEditDate: 2017-03-20T10:18:33.487Z
Answers.UserDisplayName: aergistal
Body: <p>I have a short video and I'm trying to cut-out all the blank or near blank frames.
  This isn't a case where I care about the breaks in a video that could be dark.  I literally want all near black-frames out.</p>
  
  <p>What I didn't realize with ffmpeg at first was that the 'blackframe' or 'blackdetect' filters, is that they didn't actually filter.  They just seem to show you what you can possibly filter, with other command(s).  </p>
  
  <p>What is the best way in 'Windows' to actually filter out the resulting found frames?</p>
  
  <p>So with ffmpeg I'm actually concat-(ting) the forward and reverse of the same file than I'm running some filters on those files.  See my current command:</p>
  
  <pre><code>ffmpeg.exe -y -i "2013-10-14_14-30-55.mov" -filter_complex "[0:v]transpose=3,split[tp][tp2];[tp]reverse[vr];[tp2][vr]concat=n=2:v=1:a=0[vbf];[vbf]blackframe=98:32[v]" -map "[v]" -vcodec wmv2 -q 10 -trellis 2 -r 16 "g:\gd5.wmv"
  </code></pre>
  
  <p>Then I get this output: (Just the tail end of it anyway...)</p>
  
  <pre><code>[Parsed_blackframe_4 @ 00000000003bf320] frame:650 pblack:99 pts:21821999 t:21.821999 type:B last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:651 pblack:99 pts:21855366 t:21.855366 type:P last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:652 pblack:99 pts:21888733 t:21.888733 type:B last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:653 pblack:99 pts:21922099 t:21.922099 type:B last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:654 pblack:99 pts:21955466 t:21.955466 type:I last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:655 pblack:99 pts:21988833 t:21.988833 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:656 pblack:99 pts:22022199 t:22.022199 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:657 pblack:99 pts:22055566 t:22.055566 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:658 pblack:99 pts:22088933 t:22.088933 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:659 pblack:99 pts:22122299 t:22.122299 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:660 pblack:99 pts:22155666 t:22.155666 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:661 pblack:99 pts:22189033 t:22.189033 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:662 pblack:99 pts:22222399 t:22.222399 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:663 pblack:99 pts:22255766 t:22.255766 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:664 pblack:99 pts:22289133 t:22.289133 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:665 pblack:99 pts:22322499 t:22.322499 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:666 pblack:99 pts:22355866 t:22.355866 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:667 pblack:99 pts:22389233 t:22.389233 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:668 pblack:99 pts:22422599 t:22.422599 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:669 pblack:99 pts:22455966 t:22.455966 type:I last_keyframe:669
  frame=  362 fps= 14 q=10.0 Lsize=    9004kB time=00:00:22.62   bitrate=3260.2kbits/s dup=1 drop=309
  video:8922kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.918756%
  </code></pre>
  
  <p>So what do I do with this blackframe information in Windows?  Or is there a better method with the 'blackdetect' filter?</p>
  
Tags: <video><video-editor><ffmpeg><windows>
Title: How to trim out black frames with ffmpeg on windows?
UserDisplayName: Robert Koernke
ThreadText: # How to trim out black frames with ffmpeg on windows?
  
  (Asked by: username_0 on 2015-10-07)
  
  I have a short video and I'm trying to cut-out all the blank or near blank frames.
  This isn't a case where I care about the breaks in a video that could be dark. I literally want all near black-frames out.
  
  What I didn't realize with ffmpeg at first was that the 'blackframe' or 'blackdetect' filters, is that they didn't actually filter. They just seem to show you what you can possibly filter, with other command(s).
  
  What is the best way in 'Windows' to actually filter out the resulting found frames?
  
  So with ffmpeg I'm actually concat-(ting) the forward and reverse of the same file than I'm running some filters on those files. See my current command:
  
  ```
  ffmpeg.exe -y -i "2013-10-14_14-30-55.mov" -filter_complex "[0:v]transpose=3,split[tp][tp2];[tp]reverse[vr];[tp2][vr]concat=n=2:v=1:a=0[vbf];[vbf]blackframe=98:32[v]" -map "[v]" -vcodec wmv2 -q 10 -trellis 2 -r 16 "g:\gd5.wmv"
  
  ```
  
  Then I get this output: (Just the tail end of it anyway...)
  
  ```
  [Parsed_blackframe_4 @ 00000000003bf320] frame:650 pblack:99 pts:21821999 t:21.821999 type:B last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:651 pblack:99 pts:21855366 t:21.855366 type:P last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:652 pblack:99 pts:21888733 t:21.888733 type:B last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:653 pblack:99 pts:21922099 t:21.922099 type:B last_keyframe:639
  [Parsed_blackframe_4 @ 00000000003bf320] frame:654 pblack:99 pts:21955466 t:21.955466 type:I last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:655 pblack:99 pts:21988833 t:21.988833 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:656 pblack:99 pts:22022199 t:22.022199 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:657 pblack:99 pts:22055566 t:22.055566 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:658 pblack:99 pts:22088933 t:22.088933 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:659 pblack:99 pts:22122299 t:22.122299 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:660 pblack:99 pts:22155666 t:22.155666 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:661 pblack:99 pts:22189033 t:22.189033 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:662 pblack:99 pts:22222399 t:22.222399 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:663 pblack:99 pts:22255766 t:22.255766 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:664 pblack:99 pts:22289133 t:22.289133 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:665 pblack:99 pts:22322499 t:22.322499 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:666 pblack:99 pts:22355866 t:22.355866 type:P last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:667 pblack:99 pts:22389233 t:22.389233 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:668 pblack:99 pts:22422599 t:22.422599 type:B last_keyframe:654
  [Parsed_blackframe_4 @ 00000000003bf320] frame:669 pblack:99 pts:22455966 t:22.455966 type:I last_keyframe:669
  frame=  362 fps= 14 q=10.0 Lsize=    9004kB time=00:00:22.62   bitrate=3260.2kbits/s dup=1 drop=309
  video:8922kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.918756%
  
  ```
  
  So what do I do with this blackframe information in Windows? Or is there a better method with the 'blackdetect' filter?
  
  **Tags:** video, video-editor, ffmpeg, windows
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2015-10-08. Score: 12 | Accepted answer
  
  Here's a way to do it with the `blackdetect` and `trim` filters.
  
  First, a better way to get the `blackdetect` output is via `ffprobe` because it is capable of writing structured data such as `XML`, `JSON` or one `key=value` per line.
  
  You do this using metadata injection:
  
  `ffprobe -f lavfi -i "movie=/path/to/input.mp4,blackdetect[out0]" -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet
  TAG:lavfi.black_start=0
  TAG:lavfi.black_end=5.42208
  TAG:lavfi.black_start=73.4067`
  
  As you can see it returns the start and end time of each black section. You use the returned info to `trim` the segments between each `end` and the next `start`:
  
  `ffmpeg -i /path/to/input.mp4 -filter_complex "[0:v]trim=start=5.42208:end=73.4067,setpts=PTS-STARTPTS[v1];[0:a]atrim=start=5.42208:end=73.4067,asetpts=PTS-STARTPTS[a1]" -map [v1] -map [a1] output.mp4`
  
  You can chain multiple `trim` filters in the same command. See [this answer](https://superuser.com/questions/681885/how-can-i-remove-multiple-segments-from-a-video-using-ffmpeg) for a detailed example.
  
  To automate this in Windows you can install and use [PowerShell](https://en.wikipedia.org/wiki/Windows_PowerShell) or another scripting language of your choice (PHP, Python etc).
  
  > **Comments:**
  > **username_0**: Your help is appreciated, and seems to be the right path.  However I tried the ffprobe command you suggested: `ffprobe -f lavfi -i "movie=2013-10-14_14-30-55.mov,blackdetect[out0]" -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet` But no entries come out at all. Could this be, because the frames in question are not black enough, or am I doing it wrong?  I don't understand some of the commands.  
  > **username_2**: @username_0 I used the default `blackdetect` settings, check its arguments and example on https://ffmpeg.org/ffmpeg-filters.html#blackdetect. Make sure you also have a recent version of `ffmpeg` and not a default distro installation.  
  > **username_2**: The command means: do `blackdetect`, show only `black_start` and `black_end` tags, use the default output format  `-of default` with no wrappers `nw=1` and suppress all other output `-v quiet`  
  > **username_0**: btw... You are giving me Windows instructions correct? Ok I temporarily took off the `-v quiet` and I get this: [Parsed_movie_0 @ 0056f560] Failed to avformat_open_input 'C' [lavfi @ 0056e2a0] Error initializing filter 'movie' with args 'C:UsersDOCUME~12013-10-14_14-30-55.mov' movie=C:\Users\DOCUME~1\2013-10-14_14-30-55.mov,blackdetect=d=0:pix_th=51.80[out0]: No such file or directory`  
  > **username_0**: The `-v quiet` was suppressing the error messages.  
  > **username_0**: I got it... I put the video in the same directory and ran it, and it is working.  So I'll keep testing..Thankx  
  > **username_0**: I've tried many different items in my tests.  Many times I'll get 'file not found' when clearly the file is there.  As I've shows I've tried old dos file types.  What is causing the issue here: "movie=C:\Users\INSPIR~1\DOCUME~1\a2d2\A2D2DE~1\MAC_SP~1.com\videos\2013-10-14_14-30-55.mov,blackdetect[out0]"  
  > **username_2**: When you use a path inside a command argument you have to escape the special characters or quote it, or use shorter, simple paths. https://ffmpeg.org/ffmpeg-utils.html#toc-Quoting-and-escaping  
  > **username_0**: No escaping \\..\\ seems to work.. It continues to show the error:  `Error initializing filter 'movie' with args` - The alternative is that I'm going to use is to copy to the local ffprobe/ffmpeg directory as a temp file, process it there, and then move the processed version where I need it.  Thanx.  
  > **username_0**: Finally figured out the escaping here.  I finally needed it: "movie=\'C:\\Users\\Inspiron 560\\Documents\\temp.wmv\',blackdetect[out0]" Like so... The help page linked above was vague and did not show the way for ffprobe-movie.  
  
  ---
  
  ### Answer by username_1 on 2022-01-05. Score: 2
  
  I've put together a Python script that will do all of this.
  Generates the `ffprobe` and `ffmpeg` commands and runs them And outputs a file without black clips
  
  GitHub repo: <https://github.com/username_1/deblack>
  
  GitHub gist (archived): <https://gist.github.com/username_1/eff7a7979440faa84a63657e085ec504>
  
  ```python
  """
  @author: https://github.com/username_1
  Use ffprobe to extract black frames and ffmpeg to trim them and output a new video
  """
  
  # help from:
  # https://video.stackexchange.com/questions/16564/how-to-trim-out-black-frames-with-ffmpeg-on-windows#new-answer?newreg=d534934be5774bd1938b535cd76608cd
  # https://github.com/kkroening/ffmpeg-python/issues/184#issuecomment-493847192
  
  import argparse
  import os
  import shlex
  import subprocess
  
  parser = argparse.ArgumentParser(__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  parser.add_argument('input', type=str, help='input video file')
  parser.add_argument('--invert', action='store_true', help='remove nonblack instead of removing black')
  args = parser.parse_args()
  
  ##FIXME: sadly you must chdir so that the ffprobe command will work
  os.chdir(os.path.split(args.input)[0])
  args.input = os.path.split(args.input)[1]
  
  spl = args.input.split('.')
  outpath = '.'.join(spl[:-1]) + '.' + ('invert' if args.invert else '') + 'out.' + spl[-1]
  
  def delete_back2back(l):
    from itertools import groupby
    return [x[0] for x in groupby(l)]
  
  def construct_ffmpeg_trim_cmd(timepairs, inpath, outpath):
    cmd = f'ffmpeg -i "{inpath}" -y -filter_complex '
    cmd += '"'
    for i, (start, end) in enumerate(timepairs):
      cmd += (f"[0:v]trim=start={start}:end={end},setpts=PTS-STARTPTS,format=yuv420p[{i}v]; " +
              f"[0:a]atrim=start={start}:end={end},asetpts=PTS-STARTPTS[{i}a]; ")
    for i, (start, end) in enumerate(timepairs):
      cmd += f"[{i}v][{i}a]"
    cmd += f'concat=n={len(timepairs)}:v=1:a=1[outv][outa]'
    cmd += '"'
    cmd += f' -map [outv] -map [outa] "{outpath}"'
    return cmd
  
  def get_blackdetect(inpath, invert=False):
    ffprobe_cmd = f"ffprobe -f lavfi -i \"movie={inpath},blackdetect[out0]\" -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet"
    print('ffprobe_cmd:', ffprobe_cmd)
    lines = subprocess.check_output(shlex.split(ffprobe_cmd)).decode('utf-8').split('\n')
    times = [float(x.split('=')[1].strip()) for x in delete_back2back(lines) if x]
    assert len(times), 'no black detected'
  
    if not invert:
      times = [0] + times[:-1]
    timepairs = [(times[i], times[i + 1]) for i in range(0, len(times) // 2, 2)]
    return timepairs
  
  timepairs = get_blackdetect(args.input, invert=args.invert)
  cmd = construct_ffmpeg_trim_cmd(timepairs, args.input, outpath)
  
  print(cmd)
  os.system(cmd)
  
  ```
  
  Combining multiple answers together:
  
  * <https://video.stackexchange.com/a/16571/37220>
  * <https://superuser.com/a/1498811/739491>
  
  
  ---
  
  