2016-02-16 4 views
0

Я хочу, чтобы таймер подсчета времени накладывался на видео, но все, что я мог найти в Интернете, это использование Adobe After Effects, которое на самом деле не является вариантом, поскольку я на Linux, и я не желаю платить за это.Bash - Ввести числовые переменные в команду

Итак, если бы я мог получить серию изображений или видео, то его можно было бы импортировать в Openshot, чтобы наложить видео довольно красиво, но это была борьба за передачу серии изображений или видео.

Я начал работу над скриптом, чтобы сделать серию изображений, но понятия не имею, как поместить переменные в команду. Вот сценарий в его нынешнем виде:

#!/bin/bash 
for i in {0..18000000} 
do 
    echo "$i" 
    convert -size 780x100 xc:#d3fff5ff -font Courier-New -pointsize 100 -fill black -draw "text 20,80 '000:00:00.00'" 0.png 
done 

То, что я хотел бы для 0.png, чтобы быть по существу $ i.png, поэтому он увеличивает до 18,000,000. Время (показано как 000: 00: 00.00) Возможно, я мог бы решить сам, зная, как вставлять переменные в команды. Формат времени - часы, минуты, секунды и кадры.

Вот пример, если я плохо объяснил вещи (извините за шагом - только двойные новые линии только работают здесь по какой-то причине):

0.png = 000: 00: 00,00

1.png = 000: 00: 00.01

49.png = 000: 00: 00,49

50.png = 000: 00: 01.00

51.png = 000: 00: 01.01

18000000.png = 100: 00: 00,00

+0

Почему 50.png не становится 000: 00: 00.50? Только 50 кадров в секунду? –

+0

Да, 50 кадров в секунду. Деинтерлейсированный отсчет PAL с использованием Bob. – Bob

+0

Btw: '18000000.png = 99: 59: 59.49' – Cyrus

ответ

1

Этот вид сборки основан на ответах чепнера и хоробы, а также на то, как вы получаете 18 000 000 изображений, созданных с использованием всех ядер вашего процессора. Я сравнил 3 разных метода на достойной спецификации iMac и добился следующих результатов - начиная с самого простого и медленного и оттуда до более быстрых методов ...

Метод 1 - Простой последовательный Баш скрипт

#!/bin/bash 
for ((i=0; i<18000000; i++)); do 
    f=$((i % 50)) 
    s=$(((i/50) % 60)) 
    m=$(((i/(50*60)) % 60)) 
    h=$(((i/(50*60*60)))) 
    convert -size 780x100 xc:#d3fff5ff -font Courier -pointsize 100 -fill black -draw "text 20,80 '$(printf "%03d:%02d:%02d.%02d" $h $m $s $f)'" $i.png 
done 

Это занимает около 4,6 дней, чтобы произвести 18 миллионов изображений.

Метод 2 - GNU Parallel сценарий

#!/bin/bash 

# Define a function for GNU Parallel to run 
doit() { 
    i=$1 
    f=$((i % 50)) 
    s=$(((i/50) % 60)) 
    m=$(((i/(50*60)) % 60)) 
    h=$(((i/(50*60*60)))) 
    convert -size 780x100 xc:#d3fff5ff -font Courier -pointsize 100 -fill black -draw "text 20,80 '$(printf "%03d:%02d:%02d.%02d" $h $m $s $f)'" $i.png 
} 

# Export doit() function so GNU Parallel knows about it 
export -f doit 

ulimit -S -n 2048 

for ((i=0;i<=18000000;i++)); do 
    echo $i 
done | parallel -k doit {1} 

Это сохраняет все ваши ядра процессора заняты, и занимает около 32 часов, чтобы произвести 18 миллионов файлов. Я думаю, что это довольно хороший компромисс по сравнению с необходимостью писать код, компилировать и строить его, как в следующем ответе.

Метод 3 - программа Magick ++ работает 8 копий в параллельном

#include <Magick++.h> 

using namespace std; 
using namespace Magick; 

int main(int argc, char* argv[]){ 

    // Pick up parameters 
    if(argc!=3){ 
     printf("ERROR: Please supply 2 arguments - start and end number\n"); 
     exit(EXIT_FAILURE); 
    } 
    int start=atoi(argv[1]); 
    int end =atoi(argv[2]); 

    InitializeMagick(*argv); 

    // Create a basic template 
    Image img(Geometry(780,100),Color("#d3fff5ff")); 
    img.font("Courier"); 
    img.fillColor(Color("black")); 
    img.fontPointsize(100); 

    // Get cycling through the images 
    for(int i=start;i<=end;i++){ 
     // Work out timestamp for this frame 
     int f=i % 50; 
     int s=(i/50) % 60; 
     int m=(i/(50*60)) % 60; 
     int h=(i/(50*60*60)); 
     char timestamp[100]; 
     sprintf(timestamp,"%03d:%02d:%02d.%02d",h,m,s,f); 

     // Copy the basic template image 
     Image thisframe=img; 
     thisframe.draw(Magick::DrawableText(20,80,timestamp)); 
     char filename[100]; 
     sprintf(filename,"%d.gif",i); 
     thisframe.write(filename); 
    } 
} 

Вот как вы бежите 8 копий в параллель:

#!/bin/bash 
./main 1 2250000 & 
./main 2250001 4500000 & 
./main 4500001 6750000 & 
./main 6750001 9000000 & 
./main 9000001 11250000 & 
./main 11250001 13500000 & 
./main 13500001 15750000 & 
./main 15750001 18000000 & 
wait 

Это занимает менее 9 часов, чтобы произвести 18 миллионов файлов.

+0

Мое слово, вы сделали всю работу для меня! Будет просто использовать ваш второй метод из-за баланса эффективности и простоты. ПРИМЕЧАНИЯ ДЛЯ ДРУГИХ: 'sudo apt-get install parallel' должен быть запущен для установки программного обеспечения Parallel, а _Courier-New_ должен использоваться вместо _Courier_ для моноспинга. – Bob

1

Bash расширяет переменные в командах, если они не в одинарные кавычки. Здесь они в двойных кавычках:

convert -size 780x100 xc:#d3fff5ff -font Courier-New -pointsize 100 -fill black -draw "text 20,80 '$hours:$minutes:$seconds.$frames'" $i.png 

Обратите внимание, что {0..18000000} расширяется список 18M строк первым. Лучше использовать цикл C-стиля:

for ((i=0 ; i<=18000000 ; i++)) ; do 

Еще одна проблема может заключаться в каталоге с файлами 18M. Может быть, хранить их в папках, таких как часы/минуты/секунды?

2

Математика для вычисления часы, минуты, секунды и кадры довольно просто:

f=$((i % 50)) 
s=$(((i/50) % 60)) 
m=$(((i/(50*60)) % 60)) 
h=$(((i/(50*60*60)))) 

Тогда вы можете просто вставить значения в строке следующим образом:

... -draw "text 20,80 '$(printf "%03d:%02d:%02d.%02d" $h $m $s $f)'" "$i.png" 

большая проблема как долго это займет, чтобы запустить convert 18 миллионов раз.

Смежные вопросы