Edição de vídeo de linha de comando no Linux (cortar, ingressar e visualizar)

32

Eu tenho necessidades de edição bastante simples - preciso cortar alguns vídeos, talvez inserir alguns PNGs entre eles e ingressar nesses vídeos (não precisa de transições, efeitos etc.). Basicamente, pitivifaria o que eu quero - exceto que eu uso AVIs de 640x480 a 30 qps de uma câmera e, assim que coloco mais alguns minutos desse tipo de material, pitivicomeça a congelar na visualização e, assim, fica inutilizável.

Então, comecei a procurar uma ferramenta de linha de comando para Linux; Eu acho que apenas ffmpeg( linha de comando - Usando ffmpeg para cortar vídeo - Superusuário ) e mplayer( Sam - Editar arquivo de vídeo com mencoder no linux ) são candidatos até agora, mas não consigo encontrar exemplos do uso que tenho em mente.

 

Basicamente, eu imagino que haja um codificador e ferramentas de player (como ffmpegvs ffplay; ou mencodervs mplayer) - de modo que, para começar, a sequência de edição possa ser especificada diretamente na linha de comando, preferencialmente com resolução de quadro - um pseudocódigo seria:

videnctool -compose --file=vid1.avi --start=00:00:30:12 --end=00:01:45:00 --file=vid2.avi --start=00:05:00:00 --end=00:07:12:25 --file=mypicture.png --duration=00:00:02:00 --file=vid3.avi --start=00:02:00:00 --end=00:02:45:10 --output=editedvid.avi

... ou poderia ter um arquivo de texto de "lista de reprodução", como:

vid1.avi      00:00:30:12 00:01:45:00 
vid2.avi      00:05:00:00 00:07:12:25 
mypicture.png -           00:00:02:00
vid3.avi      00:02:00:00 00:02:45:10 

... para que pudesse ser chamado com

videnctool -compose --playlist=playlist.txt --output=editedvid.avi

A ideia aqui seria que todos os vídeos estão no mesmo formato - permitindo que a ferramenta de transcodificação de evitar, e apenas fazer uma "cópia crua" em vez (como em mencoder's copiar codec: " -oac copy -ovc copy") - ou na falta disso, áudio / vídeo não compactado seria bom (apesar de consumir um pouco de espaço). No caso da imagem estática, a ferramenta usaria a codificação definida pelos arquivos de vídeo.

 

O problema é que, até agora, vejo isso mencodere ffmpegposso operar em arquivos individuais; por exemplo, cortar uma única seção de um único arquivo ou ingressar em arquivos ( mencodertambém possui Edit Decision Lists (EDL) , que pode ser usado para fazer o corte exato do quadro - para que você possa definir várias regiões de corte, mas é novamente atribuído a um único arquivo ) O que implica que eu tenho que trabalhar primeiro em cortar pedaços de arquivos individuais (cada um deles exigiria um arquivo temporário em disco) e depois juntá-los em um arquivo de vídeo final.

Imagino então que existe uma ferramenta correspondente, que pode ler o mesmo arquivo de formato / lista de opções da linha de comando da ferramenta de codificação - exceto que não gera um arquivo de saída, mas reproduz o vídeo; por exemplo, no pseudocódigo:

vidplaytool --playlist=playlist.txt --start=00:01:14 --end=00:03:13

... e, se houver memória suficiente, isso geraria uma visualização de vídeo em baixa resolução na RAM e a reproduziria em uma janela, oferecendo uma interação limitada (como mplayeros atalhos do teclado para reproduzir, pausar, retroceder, passo a passo) ) Claro, eu imaginaria os horários de início e término para se referir a toda a lista de reprodução e incluir qualquer arquivo que possa acabar nessa região na lista de reprodução.

Assim, o resultado final de tudo isso seria: operação da linha de comando; sem arquivos temporários durante a edição - e também sem arquivos temporários (nem transcodificando) ao renderizar a saída final ... o que eu acho que seria legal.

Portanto, embora eu ache que tudo isso possa ser um pouco exagerado - existe algo que se aproxime do fluxo de trabalho descrito acima?

sdaau
fonte
11
Também costumo usar o mkvmerge quando preciso dividir / participar de vídeos.
Vi.
Obrigado por isso, @Vi. - nunca tinha ouvido falar mkvmergeantes, vai ter certeza de que eu vou ver .. Felicidades!
Sdaau

Respostas:

17

Sim existe. Tente usar o aplicativo chamado "Melt". Veja a documentação aqui:

https://www.mltframework.org/docs/melt/

Se você usa uma distribuição derivada do Debian:

apt-get install melt
Ielton
fonte
no mac:brew install mlt
kraftydevil
23

Ok, como não consigo encontrar muito sobre o meltuso da linha de comando, aqui estão algumas notas .. (e depois disso, veja esta resposta Usando a substituição de processo para enganar programas que esperam arquivos, com extensões específicas como argumento? - Unix e Linux Stack Exchange para um script exemplo via bash)

Para começar - existe um pacote Ubuntu / Debian para melt(eu tenho o Ubuntu 11.04 com MLT melt 0.6.2); o link fornecido por @Ielton é para o Wiki "Media Lovin 'Toolkit" (MLT), que meltfaz parte (mas também openshote kdenlive). Aqui está o link para os arquivos de texto da documentação em seu git: mltframework.org/mlt.git/tree - docs / ; note que o wiki possui uma página sobre BuildScripts .

Por enquanto, o maior (único) problema que tenho com ele é que não consigo encontrar uma maneira de exportar uma composição de vídeo não compactada (como pngquadros ou algum formato de vídeo não compactado).

 

Primeiro, na linha de comando, meltvocê pode controlar a reprodução através de quadros; por exemplo, para "criar" um espaço em branco branco de 15 quadros e visualizá-lo com o meltplayer embutido , use

melt -blank 15

Ao visualizar com melt, você também receberá informações de linha de comando stderrpara o player incorporado:

$ melt -blank 15 
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
|1=-10| |2= -5| |3= -2| |4= -1| |5=  0| |6=  1| |7=  2| |8=  5| |9= 10|
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
+---------------------------------------------------------------------+
|               H = back 1 minute,  L = forward 1 minute              |
|                 h = previous frame,  l = next frame                 |
|           g = start of clip, j = next clip, k = previous clip       |
|                0 = restart, q = quit, space = play                  |
+---------------------------------------------------------------------+
Current Position:         15

Uma vez que melté feito jogando para trás, ele não vai sair - assim que você deve digitar qpara sair dela.

Devemos observar que existem os chamados "produtores" e "consumidores" em melt. Se nada for especificado, o "consumidor" padrão é uma janela SDL (Simple DirectMedia Layer) reproduzindo o vídeo; portanto, o comando acima é o mesmo que:

melt -blank 15 -consumer sdl

Portanto, se quisermos salvar o que é meltexibido, devemos mudar o consumidor para algo que suporte um formato de arquivo. Para obter uma lista de consumidores:

$ melt -query "consumers"
---
consumers:
  - sdl
  - sdl_audio
  - sdl_preview
  - sdl_still
  - gtk2_preview
  - avformat
  - libdv
  - xml
  - decklink
  - null
...

O libdvconsumidor enviará dados formatados em DV diretamente para stdout, para salvar o vídeo em um .dvarquivo que você faria:

melt -blank 15 -consumer libdv > test.dv

Observe que, dos consumidores listados, o único formato que tentei, que também pode ser aberto em outro aplicativo, é libdv(usei vlccomo outro aplicativo); no entanto, isso pode falhar para um tipo diferente de transcodificação ( por exemplo, se, em vez de um espaço em branco, eu tentar converter um trecho de .flvarquivo, o arquivo .dv resultante será aberto e reproduzido vlc, mas está corrompido ).

 

Agora para a parte de edição ; essencialmente, você pode especificar uma série de estrofes de nome de arquivo / entrada / saída diretamente na linha de comando; digamos que você tenha um arquivo, video.avi- então você pode fazer:

melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79

ou um pouco melhor formatado:

melt \ 
video.avi in=30 out=79 \ 
-blank 15 \
video.avi in=30 out=79

Isto significa que video.avido seu quadro 30 para o seu quadro 79 será reproduzido; então um espaço em branco de 15 quadros; e então a video.avisequência do quadro 30 para o quadro 79 novamente.

Para utilizar imagens (por exemplo .png) em uma composição de edição de vídeo:

melt \
video.avi in=30 out=79 \
test.png in=0 out=15 \
video.avi in=30 out=79 \
-blank 15

Observe que para test.png, o in=parâmetro não precisa ser 0 - no entanto, a imagem será exibida por out- intempo; nesse caso, seria mais fácil simplesmente deixar o in=0parâmetro totalmente de fora.

 

O bom é que essa sequência de edição pode ser salva - ou como é meltchamada, serializada - em um arquivo; observe que existem duas maneiras de tal serialização: "simples" ou XML. Por exemplo, para salvar o comando acima como um arquivo serializado "simples", podemos apenas adicionar a -serialise [filename]opção ao comando:

$ melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79 -serialise file.melt 
Project saved as file.melt.

Agora o file.meltcontém:

video.avi
in=30
out=79
-blank
15
video.avi
in=30
out=79

Aparentemente, esse formato de arquivo serializado "simples" não contém um caractere "comentando" - se eu tentar adicionar uma # commentlinha " ", meltqueixa-se de: ' Falha ao carregar "# comment" ' (mas, além disso, parece que uma linha é ignorada e a reprodução continua de qualquer maneira). " .melt" parece ser uma extensão que meltreconhece como um arquivo serializado simples.

Agora, para reproduzir novamente esse arquivo serializado, poderíamos, em princípio, apenas chamar melt file.melt- no entanto, uma linha de comando mais completa seria:

melt melt_file:file.melt -consumer sdl

... o que significaria: use o melt_file"produtor" para abrir file.melte renderize seus quadros no "consumidor" sdl(janela).

Observe que tenho a experiência de que (digamos) os .flvvídeos são reproduzidos sem problemas na linha de comando - no entanto, causam uma falha de segmentação quando são especificados no file.meltarquivo serializado! .dvvídeos produzidos por meltsi só, parecem funcionar bem em file.melt...

 

O tipo XML de serialização pode ser alcançado usando a -consumer xml:opção (em vez de-serialise ) - portanto, o exemplo acima seria agora:

melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79 -consumer xml:file.mlt

Para "reproduzir" o file.mltarquivo XML recém-gerado , agora é possível executar diretamente melt file.mlt- ou, uma linha de comando mais completa seria:

melt xml:file.mlt -consumer sdl

... o que significaria: use o xml"produtor" ( observe que anteriormente era consumidor ) para abrir file.mlte renderizar seus quadros no "consumidor" sdl(janela).

Observe que, nesse caso, eu experimentei que os mesmos .flvvídeos que causaram segfault com um arquivo de serialização simples - funcionam bem com um arquivo de serialização XML!

Nesse caso, o file.mltarquivo XML resultante possui muito mais configurações, como resolução, taxa de quadros, informações de codec etc. - mas também é mais difícil trabalhar diretamente em um editor de texto:

<?xml version="1.0" encoding="utf-8"?>
<mlt root="/path/to" title="video.avi">
  <profile description="automatic" width="320" height="240" progressive="1" sample_aspect_num="1" sample_aspect_den="1" display_aspect_num="320" display_aspect_den="240" frame_rate_num="25" frame_rate_den="1" colorspace="601"/>
  <producer id="producer0" in="30" out="79">
    <property name="mlt_type">producer</property>
    <property name="aspect_ratio">1.000000</property>
    <property name="length">125</property>
    <property name="eof">pause</property>
    <property name="resource">video.avi</property>
    <property name="meta.media.nb_streams">2</property>
    <property name="meta.media.0.stream.type">video</property>
    <property name="meta.media.0.stream.frame_rate">25.000000</property>
    <property name="meta.media.0.stream.sample_aspect_ratio">0.000000</property>
    <property name="meta.media.0.codec.frame_rate">25.000000</property>
    <property name="meta.media.0.codec.pix_fmt">yuv420p</property>
    <property name="meta.media.0.codec.sample_aspect_ratio">1.000000</property>
    <property name="meta.media.0.codec.colorspace">601</property>
    <property name="meta.media.0.codec.name">mpeg4</property>
    <property name="meta.media.0.codec.long_name">MPEG-4 part 2</property>
    <property name="meta.media.0.codec.bit_rate">0</property>
    <property name="meta.media.1.stream.type">audio</property>
    <property name="meta.media.1.codec.sample_fmt">s16</property>
    <property name="meta.media.1.codec.sample_rate">22050</property>
    <property name="meta.media.1.codec.channels">1</property>
    <property name="meta.media.1.codec.name">mp2</property>
    <property name="meta.media.1.codec.long_name">MP2 (MPEG audio layer 2)</property>
    <property name="meta.media.1.codec.bit_rate">64000</property>
    <property name="seekable">1</property>
    <property name="meta.media.sample_aspect_num">1</property>
    <property name="meta.media.sample_aspect_den">1</property>
    <property name="meta.attr.title.markup"></property>
    <property name="meta.attr.author.markup"></property>
    <property name="meta.attr.copyright.markup"></property>
    <property name="meta.attr.comment.markup"></property>
    <property name="meta.attr.album.markup"></property>
    <property name="audio_index">1</property>
    <property name="video_index">0</property>
    <property name="mlt_service">avformat</property>
  </producer>
  <producer id="producer1" in="30" out="79">
    <property name="mlt_type">producer</property>
    <property name="aspect_ratio">1.000000</property>
    <property name="length">125</property>
    <property name="eof">pause</property>
    <property name="resource">video.avi</property>
    <property name="meta.media.nb_streams">2</property>
    <property name="meta.media.0.stream.type">video</property>
    <property name="meta.media.0.stream.frame_rate">25.000000</property>
    <property name="meta.media.0.stream.sample_aspect_ratio">0.000000</property>
    <property name="meta.media.0.codec.frame_rate">25.000000</property>
    <property name="meta.media.0.codec.pix_fmt">yuv420p</property>
    <property name="meta.media.0.codec.sample_aspect_ratio">1.000000</property>
    <property name="meta.media.0.codec.colorspace">601</property>
    <property name="meta.media.0.codec.name">mpeg4</property>
    <property name="meta.media.0.codec.long_name">MPEG-4 part 2</property>
    <property name="meta.media.0.codec.bit_rate">0</property>
    <property name="meta.media.1.stream.type">audio</property>
    <property name="meta.media.1.codec.sample_fmt">s16</property>
    <property name="meta.media.1.codec.sample_rate">22050</property>
    <property name="meta.media.1.codec.channels">1</property>
    <property name="meta.media.1.codec.name">mp2</property>
    <property name="meta.media.1.codec.long_name">MP2 (MPEG audio layer 2)</property>
    <property name="meta.media.1.codec.bit_rate">64000</property>
    <property name="seekable">1</property>
    <property name="meta.media.sample_aspect_num">1</property>
    <property name="meta.media.sample_aspect_den">1</property>
    <property name="meta.attr.title.markup"></property>
    <property name="meta.attr.author.markup"></property>
    <property name="meta.attr.copyright.markup"></property>
    <property name="meta.attr.comment.markup"></property>
    <property name="meta.attr.album.markup"></property>
    <property name="audio_index">1</property>
    <property name="video_index">0</property>
    <property name="mlt_service">avformat</property>
  </producer>
  <playlist id="playlist0">
    <entry producer="producer0" in="0" out="49"/>
    <blank length="16"/>
    <entry producer="producer1" in="0" out="49"/>
  </playlist>
  <tractor id="tractor0" title="video.avi" global_feed="1" in="0" out="115">
    <track producer="playlist0"/>
  </tractor>
</mlt>
sdaau
fonte
Além disso, aqui está um exemplo para cortes com precisão de quadro: Cortar arquivos de vídeo com precisão da linha de comando - Super User
sdaau
7

A solução ffmpeg para esse problema é mais ou menos assim:

mkfifo temp1 temp2 temp3
ffmpeg -i input.wmv -ss 30 -to 60 -c copy output.wmv temp1 2> /dev/null & \
ffmpeg -i input2.wmv -t 60 -c copy temp2 2> /dev/null & \
ffmpeg -i input3.wmv -i image.png -filter_complex "[0:v][1:v] \
overlay=25:25:enable='between(t,0,20)'" -pix_fmt yuv420p -c:a copy temp3 2> /dev/null & \
ffmpeg -f mpegts -i "concat:temp1|temp2|temp3" -c copy output.mp4

Ele usa pipes nomeados, portanto, não há como criar arquivos temporários no disco e permite cortar pedaços dos clipes de vídeo e adicionar imagens.

Este exemplo usa o tempo de 30 a 60 da primeira entrada e, em seguida, adiciona o primeiro minuto da segunda entrada, insere um arquivo de imagem e o terceiro vídeo inteiro.

Código retirado de:

Página de concatenação do ffmpeg: https://trac.ffmpeg.org/wiki/Concatenate

página de superusuário Usando ffmpeg para cortar vídeo

página de superusuário https://video.stackexchange.com/questions/12105/add-an-image-in-front-of-video-using-ffmpeg

codeMonkey
fonte
Obrigado por isso, eu também aprendi recentemente sobre o ffmpeg-concat , que está escrito em JavaScript (e você precisa npminstalá-lo), então pensei em mencioná-lo
sdaau
4

Eu também tenho procurado por essa ferramenta e parece que derreter é a ferramenta para o trabalho, no entanto, a documentação é quase impossível de entender / ausente. Você pode fazer quase qualquer combinação de edição. Eu tinha algumas filmagens de 'câmera de ação' ... o som era inutilizável. Entrei no vídeo (h264), adicionei um fade de 60 quadros e substituí o som por uma trilha sonora usando:

% melt -video-track vid1.avi vid2.avi -mix 60 -mixer luma vid3.avi \
   -mix 60 -mixer luma -audio-track vorbis:track1.ogg vorbis:track2.ogg \
   -consumer avformat:OUT.avi acodec=libmp3lame vcodec=libx264

Você pode ler mais sobre isso aqui . O site principal está aqui .

user196805
fonte