FFMPEG Generate N Равномерно PNG Скриншоты - PullRequest
3 голосов
/ 22 июля 2010

Я пытаюсь создать 8 скриншотов для загруженного видео с помощью FFMPEG.В настоящее время у меня есть:

ffmpeg -i Trailer-720p.mov -r .2 -vcodec png Preview-% d.png

, который генерирует скриншот каждые 5 секунд,Как добавить возможность создания снимка экрана для кадров, распределенных по процентам от общего времени.Благодарю.Кроме того, возможно ли создать скриншот на 50%, например?Спасибо.

Ответы [ 4 ]

9 голосов
/ 02 августа 2010

Если вы запустите ffmpeg только с параметром -i, он предоставит вам длину видео на stderr (среди прочего).Вы можете написать что-нибудь об этом, преобразовав длительность и предполагаемое количество кадров в правильный параметр -r.

Вот краткий пример на python, который в основном выполняет то, что я описал.По некоторым причинам первые два кадра, сгенерированные моей версией ffmpeg, показывают кадр 0, но с Preview-3 до Preview-n находятся в правильных интервалах.Запустите его со вторым параметром, установленным в '1', и он сгенерирует средний кадр как Preview-3.png.

#!/usr/bin/env python

import sys,os,re
from subprocess import *

if len(sys.argv)<=1:
  print("usage: python oneinn.py filename frames")
  sys.exit(0)

try:
  fvideo = sys.argv[1]
  frames = float(sys.argv[2])
except:
  sys.stderr.write("Failed to parse parameters.\n")
  sys.exit(1)

output = Popen(["ffmpeg", "-i", fvideo], stderr=PIPE).communicate()

# searching and parsing "Duration: 00:05:24.13," from ffmpeg stderr, ignoring the centiseconds
re_duration = re.compile("Duration: (.*?)\.")
duration = re_duration.search(output[1]).groups()[0]

seconds = reduce(lambda x,y:x*60+y,map(int,duration.split(":")))
rate = frames/seconds

print("Duration = %s (%i seconds)" % (duration, seconds))
print("Capturing one frame every %.1f seconds" % (1/rate))

output = Popen(["ffmpeg", "-i", fvideo, "-r", str(rate), "-vcodec", "png", 'Preview-%d.png']).communicate()
7 голосов
/ 04 июля 2014

Или просто с помощью команды оболочки:

ffmpeg -i input.m4v -vf fps = 1 / $ (echo 'scale = 6;' $ (ffprobe -loglevel quiet -of 'compact = nokey = 1: print_section = 0' -show_format_entry длительность input.m4v) '/ 10' | bc) -vframes 10 -qscale: v 2 thumbnail-% d.png

Это создает 10 миниатюр с теми же размерами, что и исходное видео.

3 голосов
/ 30 августа 2011

Вот один в Ruby:

#!/usr/bin/env ruby
# pass the video source file(s) into the command line args
# resulting images are jpg, just change the appropriate ffmpeg option for png.
# the last line uses ImageMagick to stitch the images together into a strip.    
# the first image is thrown away, since it's a duplicate of the second image.

ARGV.each do|a|
  total_shots = 4
  size = '200x200'
  meta = %x(ffmpeg -i #{a} 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//)
  time_parts = meta.match /(\d\d):(\d\d):(\d\d)\.(\d\d)/
  duration_seconds = time_parts[1].to_i*60*60+time_parts[2].to_i*60+time_parts[3].to_i+time_parts[4].to_f/100
  puts "*** Duration seconds: " +  duration_seconds.to_s
  %x(ffmpeg -i #{a} -r #{total_shots/duration_seconds} -s #{size} -f image2 -vframes #{total_shots+1} foo-%03d.jpg )
  files = (1..total_shots+1).map{|i| 'foo-' + ("%03d" % i) + '.jpg'}
  files.delete_at 0
  %x(convert -append #{files.join ' '} shot-strip.jpg)
end
1 голос
/ 31 мая 2016

Я не мог заставить блестящего oneliner Манфреда Стинстра генерировать кадры в нужном месте.Если бы я указал, что нужно сгенерировать 8 изображений из фильма продолжительностью 240 секунд, первое будет 15, второе - 45, и так далее.Я хотел, чтобы первый был 0, второй - 30, и так далее.

Поэтому я разобрал его oneliner на части и создал этот

ffmpeg=../bin/ffmpeg
ffprobe=../bin/ffprobe
outdir=../test
infile=../testmovie.mp4
outbase=testmovie

steps=8

len=`$ffprobe -loglevel quiet -of 'compact=nokey=1:print_section=0' -show_format_entry duration $infile`
echo length $len

secs=`echo 'scale=6;' $len ' /  ' $steps | bc`
echo secs $secs

for ((i=0; i <= $steps ; i++)); do
    echo =========================
    echo $ffmpeg -nostats -loglevel 0 \
            -i $infile -f image2 -ss `echo $secs \* $i | bc` \
             -vframes 1 "$outdir/$outbase"-$i.jpg
    $ffmpeg -nostats -loglevel 0 \
            -i $infile -f image2 -ss `echo $secs \* $i | bc`  \
             -vframes 1 "$outdir/$outbase"-$i.jpg
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...