media assets: fix incorrect frame counts for certain .webm files.

Fix calculating incorrect frame counts for certain .webm files. An
example is https://danbooru.donmai.us/media_assets/5968481.

Caused by ffmpeg printing multiple `frame= NNN` lines, and us taking the
first one instead of the last one:

    frame=    1 fps=0.0 q=-0.0 size=N/A time=00:00:00.08 bitrate=N/A speed=2.07x    
[null @ 0x56046ff4e440] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 321 >= 321
    [null @ 0x56046ff4e440] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 321 >= 321
    frame=  395 fps=0.0 q=-0.0 size=N/A time=00:00:06.66 bitrate=N/A speed=12.3x    
frame=  791 fps=759 q=-0.0 size=N/A time=00:00:13.26 bitrate=N/A speed=12.7x    
frame= 1193 fps=772 q=-0.0 size=N/A time=00:00:19.94 bitrate=N/A speed=12.9x    
frame= 1374 fps=780 q=-0.0 Lsize=N/A time=00:00:22.86 bitrate=N/A speed=  13x
    video:719kB audio:4288kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
This commit is contained in:
evazion
2022-11-03 22:01:51 -05:00
parent 5f8fefccaa
commit cb35bad237

View File

@@ -180,15 +180,16 @@ class FFmpeg
def playback_info
# XXX `-c copy` is faster, but it doesn't decompress the stream so it can't detect corrupt videos.
output = shell!("ffmpeg -hide_banner -i #{file.path.shellescape} -f null /dev/null")
lines = output.split(/\r\n|\r|\n/)
# time_line = "frame= 10 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.48 bitrate=N/A speed= 179x"
# time_info = { "frame"=>"10", "fps"=>"0.0", "q"=>"-0.0", "Lsize"=>"N/A", "time"=>"00:00:00.48", "bitrate"=>"N/A", "speed"=>"188x" }
time_line = output.lines.grep(/\Aframe=/).first.chomp
time_line = lines.grep(/\Aframe=/).last.strip
time_info = time_line.scan(/\S+=\s*\S+/).map { |pair| pair.split(/=\s*/) }.to_h
# size_line = "video:36kBkB audio:16kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown"
# size_info = { "video" => 36000, "audio" => 16000, "subtitle" => 0, "other streams" => 0, "global headers" => 0, "muxing overhead" => 0 }
size_line = output.lines.grep(/\Avideo:/).first.chomp
size_line = lines.grep(/\Avideo:/).last.strip
size_info = size_line.scan(/[a-z ]+: *[a-z0-9]+/i).map do |pair|
key, value = pair.split(/: */)
[key.strip, value.to_i * 1000] # [" audio", "16kB"] => ["audio", 16000]