簡體   English   中英

ffmpeg 創建縮略圖精靈的命令

[英]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

它會自動生成所需圖片的數量,讓您一目了然。

MR_1204給出答案的一點改進建議:如果最終精靈是PNG,我會避免JPG壓縮導致的質量下降,而是將臨時縮略圖保存為PNG:

ffmpeg -i sprite/MyVideoFile.mp4 -r 1 -s 280x180 -f image2 sprite/thumbs/thumb-%%d.png

此外,保存到 PNG 通常比保存到 JPG 快一點(微小)。

相反,為了保持下載量較小,將(僅)最終精靈圖像保存為 JPG 可能是有意義的,在 PHP 和 GD 的情況下,這僅需要將 imagepng(...) 替換為 imagejpeg(...)。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM