Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you put the result of a blackdetect filter in a textfile using ffmpeg?

Tags:

ffmpeg

I'm testing out the "blackdetect" filter in ffmpeg. I want to have the times when the video is black to be read by a script (like actionscript or javascript). I tried:

ffmpeg -i video1.mp4 -vf "blackdetect=d=2:pix_th=0.00" -an -f null -

And I get a nice result in the ffmpeg log:

ffmpeg version N-55644-g68b63a3 Copyright (c) 2000-2013 the FFmpeg developers
  built on Aug 19 2013 20:32:00 with gcc 4.7.3 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-av
isynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enab
le-iconv --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetyp
e --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --ena
ble-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-l
ibopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libsp
eex --enable-libtheora --enable-libtwolame --enable-libvo-aacenc --enable-libvo-
amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --
enable-libxvid --enable-zlib
  libavutil      52. 42.100 / 52. 42.100
  libavcodec     55. 28.100 / 55. 28.100
  libavformat    55. 13.103 / 55. 13.103
  libavdevice    55.  3.100 / 55.  3.100
  libavfilter     3. 82.100 /  3. 82.100
  libswscale      2.  5.100 /  2.  5.100
  libswresample   0. 17.103 /  0. 17.103
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01 00:00:00
    encoder         : Lavf53.13.0
  Duration: 00:02:01.54, start: 0.000000, bitrate: 275 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 768x432 [
SAR 1:1 DAR 16:9], 211 kb/s, 25 fps, 25 tbr, 25 tbn, 50 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
      handler_name    : VideoHandler
    Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 59
 kb/s
    Metadata:
      creation_time   : 1970-01-01 00:00:00
      handler_name    : SoundHandler
Output #0, null, to 'pipe:':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf55.13.103
    Stream #0:0(eng): Video: rawvideo (I420 / 0x30323449), yuv420p, 768x432 [SAR
 1:1 DAR 16:9], q=2-31, 200 kb/s, 90k tbn, 25 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
      handler_name    : VideoHandler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 -> rawvideo)
Press [q] to stop, [?] for help
[null @ 00000000003279a0] Encoder did not produce proper pts, making some up.
[blackdetect @ 0000000004d5e800] black_start:0 black_end:17.08 black_duration:17
.08
[blackdetect @ 0000000004d5e800] black_start:62.32 black_end:121.48 black_durati
on:59.16
frame= 3038 fps=2317 q=0.0 Lsize=N/A time=00:02:01.52 bitrate=N/A
video:285kB audio:0kB subtitle:0 global headers:0kB muxing overhead -100.007543%

And I'm particularly interested in this part:

[blackdetect @ 0000000004e2e340] black_start:0 black_end:17.08 black_duration:17.08
[blackdetect @ 0000000004e2e340] black_start:62.32 black_end:121.48 black_duration:59.16

So my question:

  1. Is there a way to only take the blackdetect filter output and put it in a .txt file?
  2. And if this is possible, is there a way to do this in a statement with multiple video inputs? Like in this example

example:

ffmpeg -f concat -i mylist.txt -c copy concat.mp4

Where mylist.txt is a list of videos:

file 'video1.mp4'
file 'video2.mp4'
file 'video3.mp4'
file 'video4.mp4'

Basically what I want to have is one or more text files containing information about the black frames in every video in this list to be used by another program

like image 630
Gijserman Avatar asked Sep 10 '13 15:09

Gijserman


2 Answers

If using ffprobe is acceptable there is now a simpler way to do it with metadata injection:

ffprobe -f lavfi -i "movie=input.mp4,blackdetect[out0]" -show_entries tags=lavfi.black_start,lavfi.black_end -of default=nw=1 -v quiet

The command outputs only the lavfi tags black_start and black_end.

The advantage is you can also get frame information etc, or multiple tags in a format which is easier to parse.

ffprobe can also output JSON or XML but I can't find a way to skip the frames with no tags which produce empty nodes. This should be easy to patch though.

like image 85
aergistal Avatar answered Oct 05 '22 11:10

aergistal


See aergistal's answer for a newer, simpler method that was not available at the time this answer was made

Is there a way to only take the blackdetect filter output and put it in a .txt file?

By default ffmpeg logs to stderr. You can output to stdout and then use grep to isolate the blackdetect lines:

$ ffmpeg -i video1.mp4 -vf "blackdetect=d=2:pix_th=0.00" -an -f null - 2>&1 | grep blackdetect > output.txt

Resulting in:

$ cat output.txt 
[blackdetect @ 0x1d2b980] black_start:5.16 black_end:10.24 black_duration:5.08 

If you want to append to output.txt instead of overwriting for each instance then use >> instead of >, as in: blackdetect >> output.txt.


Is there a way to do this in a statement with multiple video inputs?

You can use blackdetect with the concat demuxer as shown in your question, but be aware that the black_start and black_end times will be cumulative, and not independent to each input, because you are concatenating all inputs.

Alternatively you can use a bash "for loop" if you want each input to be independently run through blackdetect:

for f in *.mp4; do ffmpeg -i "$f" -vf "blackdetect=d=2:pix_th=0.00" -an -f null - 2>&1 | grep blackdetect > "$f".txt; done

This may create empty txt files.

like image 23
llogan Avatar answered Oct 05 '22 13:10

llogan