[英]To convert the extension of a file to the different directory by a ffmpeg command
[英]ffmpeg command to create thumbnail sprites
從 ffmpeg 到 output 單幀我可以這樣做:
ffmpeg -i input.flv -ss 00:00:14.435 -vframes 1 out.png
對於每秒 output 一張圖像,我可以這樣做:
ffmpeg -i input.flv -vf fps=1 out%d.png
是否有一種方法可以從這些輸出中創建一個縮略圖精靈,以幫助為搜索 position 上的拇指創建一個 vtt 文件?
這是一個使用 ffmpeg 從 mp4 視頻創建 jpeg 文件(280x180)的示例,然后使用 PHP gd2 + 為視頻播放器編寫 VTT 文件將此縮略圖組裝成精靈(png 格式)。
首先使用 ffmpeg 每秒創建 1 個圖像:
ffmpeg -i sprite/MyVideoFile.mp4 -r 1 -s 280x180 -f image2 sprite/thumbs/thumb-%%d.jpg
然后創建精靈文件 + vtt 文件(以 PHP 為例):
$dirToScan = 'thumbs/';
$filePrefix = 'thumb-';
$fileSuffix = '.jpg';
$thumbWidth = 280;
$thumbHeight = 180;
$imageFiles = array();
$spriteFile = 'sprite.png';
$imageLine = 20;
$vttFile = 'sprite.vtt';
$dst_x = 0;
$dst_y = 0;
# read the directory with thumbnails, file name in array
foreach (glob($dirToScan.$filePrefix.'*'.$fileSuffix) as $filename) {
array_push($imageFiles,$filename);
}
natsort($imageFiles);
#calculate dimension for the sprite
$spriteWidth = $thumbWidth*$imageLine;
$spriteHeight = $thumbHeight*(floor(count($imageFiles)/$imageLine)+1);
# create png file for sprite
$png = imagecreatetruecolor($spriteWidth,$spriteHeight);
# open vtt file
$handle = fopen($vttFile,'wb+');
fwrite($handle,'WEBVTT'."\n");
# insert thumbs in sprite and write the vtt file
foreach($imageFiles AS $file) {
$counter = str_replace($filePrefix,'',str_replace($fileSuffix,'',str_replace($dirToScan,'',$file)));
$imageSrc = imagecreatefromjpeg($file);
imagecopyresized ($png, $imageSrc, $dst_x , $dst_y , 0, 0, $thumbWidth, $thumbHeight, $thumbWidth,$thumbHeight);
$varTCstart = gmdate("H:i:s", $counter-1).'.000';
$varTCend = gmdate("H:i:s", $counter).'.000';
$varSprite = $spriteFile.'#xywh='.$dst_x.','.$dst_y.','.$thumbWidth.','.$thumbHeight;
fwrite($handle,$counter."\n".$varTCstart.' --> '.$varTCend."\n".$varSprite."\n\n");
create new line after 20 images
if ($counter % $imageLine == 0) {
$dst_x=0;
$dst_y+=$thumbHeight;
}
else {
$dst_x+=$thumbWidth;
}
}
imagepng($png,$spriteFile);
fclose($handle);
VTT 文件如下所示:
WEBVTT
1
00:00:00.000 --> 00:00:01.000
sprite.png#xywh=0,0,280,180
2
00:00:01.000 --> 00:00:02.000
sprite.png#xywh=280,0,280,180
3
00:00:02.000 --> 00:00:03.000
sprite.png#xywh=560,0,280,180
...
我不完全確定您對 vtt 文件的 sprite 需要/意味着什么,但是有一個很好的工具可以讓您將單個圖像組合成一個大的概覽圖片:
ImageMagick附帶一個名為montage
的方便工具
蒙太奇 - 通過組合多個單獨的圖像來創建合成圖像。 圖像平鋪在合成圖像上,可選地裝飾有邊框、框架、圖像名稱等。
您可以使用以下命令將縮略圖放在一張或多張圖像上:
montage *.png -tile 4x4 overview.png
它會自動生成所需圖片的數量,讓您一目了然。
Python MR_1204的解決方案
import ffmpeg
import logging
from pathlib import Path
from config import temp
import os
from PIL import Image
from datetime import datetime, timedelta
import math
logger = logging.getLogger(__name__)
class ScreenshotExtractor:
def __init__(self):
self.screenshot_folder = f"{temp}ss"
self.gap = 10
self.size = "177x100"
self.col = 5
self.ss_width = 177
self.ss_height = 100
def create_sprite_sheet(self, name):
path, dirs, files = next(os.walk(self.screenshot_folder))
file_count = len(files)
img_width = self.ss_width * self.col
img_height = self.ss_height * math.ceil(file_count/self.col)
file_name = f"{name}.jpg"
out_image = Image.new('RGB', (img_width, img_height))
webvtt = "WEBVTT\n\n"
for count, img_file in enumerate(files):
img = Image.open(f"{self.screenshot_folder}/{img_file}")
st_time = timedelta(seconds=count * self.gap)
end_time = timedelta(seconds=(count + 1) * self.gap)
# Adding img to out_file
x_mod = int(count / self.col)
x = 0 + (count - (self.col * x_mod)) * self.ss_width
y = 0 + x_mod * self.ss_height
out_image.paste(img, (x, y))
sprite = f"{file_name}#xywh={x},{y},{self.ss_width},{self.ss_height}"
webvtt += f"{count + 1}\n0{str(st_time)}.000 --> 0{str(end_time)}.000\n{sprite}\n\n"
out_image.save(f"{temp}{file_name}", quality=90)
f = open(f"{temp}{name}.vtt", "w")
f.write(webvtt)
f.close()
return True
def extract_screenshots(self, file_uri, name):
try:
Path(self.screenshot_folder).mkdir(parents=True, exist_ok=True)
vod = ffmpeg.input(file_uri)
vod.output(f"{self.screenshot_folder}/{name}_%04d.png", r=1/self.gap, s=self.size).run()
return True
except Exception as e:
logger.warning(e)
return False
def run(self, file_uri, name):
# TODO - Actually do logic here
self.extract_screenshots(file_uri, name)
self.create_sprite_sheet(name)
希望這有助於某人
所有這些解決方案對我來說都過於復雜。 正手你唯一需要的是視頻輸入的幀速率和持續時間(以秒為單位)(ffprobe)。 只需執行以下給出的實際示例(python):
sprites_output = str(job['output_dir'] + '/' + 'sprites.webp')
tile_rows = math.ceil(job["duration"] / 100)
frame_modulus = math.ceil(float(job["video"][0]["frame_rate"]) * 10)
# Create sprites
command_string = f'{options["path_ffmpeg"]} -i "{job["input"]}" -vf "select=not(mod(n\,{frame_modulus})),scale=192:108,tile=10x{tile_rows}" "{sprites_output}"'
task_command = subprocess.Popen(command_string, shell=True, stdout=subprocess.PIPE)
task_command.wait()
這將在 10 張圖片的寬度上每 10 秒為您提供一個新幀,所有圖片都打包到一個 webp 文件中。 如果您想要不同的格式,只需更改 output 擴展名,ffmpeg 會為您處理。 此外,這比任何 python 腳本都快得多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.