Como alterar a taxa de quadros de um vídeo sem recodificar

14

Estou tentando alterar a taxa de quadros de um vídeo MP4 (é um vídeo GoPro de 120fps, quero reproduzi-lo a 30fps para um efeito de câmera lenta).

Estou usando o avconv para isso:

avconv -i SourceMovie.mp4 -vf setpts=4.0*PTS -r 30 DestMovie.mp4

Isso tecnicamente funciona, mas recodifica o filme. Além de lento, é obviamente um problema de qualidade. Tecnicamente, deve haver uma maneira de definir os fps no cabeçalho do vídeo, como posso mudar isso? (Qualquer ferramenta que não seja o avconv também funcionaria.)

EboMike
fonte

Respostas:

15

MP4Box pode fazê-lo.

O comando

MP4Box -add SourceMovie.mp4#video -raw 1 -new test

cria os arquivos teste test_track1.h264. Agora você pode criar um arquivo mp4 com qualquer taxa de quadros suportada que desejar (30 neste exemplo):

MP4Box -add test_track1.h264:fps=30 -new DestMovie.mp4

O MP4Box faz parte do gpacpacote, portanto, verifique se ele está instalado.

Mitch
fonte
6
Realmente não é simples, mas entendi - você precisa fazer isso em duas etapas. Primeiro, extraia o fluxo de vídeo separadamente como raw ( MP4Box -add source.mp4#video -raw 1 -new test) e depois salve-o como um MP4 novamente ( MP4Box -add test_track1.h264:fps=30 -new dest.mp4). Você também pode adicionar uma faixa de áudio (via #audio).
EboMike
É melhor usar a -singleopção para o primeiro comando. MP4Box -single 1 -raw 1 SourceMovie.mp4cria apenas um arquivo em SourceMovie_track1.h264vez de dois.
diversenok
6

Alterar a taxa de quadros no cabeçalho do vídeo (contêiner) não afeta o fluxo de vídeo (ou fluxo de áudio). A recodificação é a única opção.

Os fluxos de vídeo têm registros de data e hora e, na maioria dos vídeos, os quadros são interdependentes entre si devido à compactação entre quadros. Alguns players podem acelerar e desacelerar o vídeo, mas não por comandos incorporados ou algo assim. Nenhum jogador pode alterar a taxa de quadros em tempo real quando um comando de contêiner solicitar. O arquivo de vídeo ficará fora da especificação (ou seja, não segue os padrões) e 99,9% dos jogadores se recusarão a cumpri-lo. É completamente impossível fazer o que você deseja sem recodificar. Claro que você pode esperar com a recodificação até a última etapa da sua edição.

thom
fonte
1
Obrigado thom! Pergunta estúpida - por quê? Cada quadro possui um registro de data e hora que obriga o player a impor uma certa velocidade de reprodução? Eu quero exatamente os mesmos quadros, só quero que eles sejam reproduzidos em uma taxa diferente.
EboMike
2
Oi Mike, não, sua pergunta não é estúpida, francamente da maneira que você acha que é bastante inteligente. Eu gosto do seu modo de pensar. Eu adicionei mais informações à minha resposta porque era muito longo para colocar isso na caixa de comentários.
Thom
Obrigado! Isso é bastante informativo. Agora, quanto à recodificação - qual é a melhor maneira de fazer isso com algo como avconv? Eu usei a linha de comando acima, mas isso resultou em uma qualidade horrível - eu quase conseguia ver todos os macroblocos.
EboMike
1
Os carimbos de hora nos fluxos de vídeo são armazenados no contêiner, não no próprio fluxo de bits h.264, eu acho. Contanto que você queira alterar o tempo, mas não a ordem, para qual quadro será exibido quando, você não precisará transcodificar, apenas remuxar. (E se você fizer xcode, com um hardware mais rápido, use -preset mais lento ou mais lento para obter mais qualidade na mesma taxa de bits, em vez de apenas jogar mais bits no problema. E use -crf 18 ou algo assim, não ABR)
Peter Cordes
1
Não consigo descobrir como fazer com que o ffmpeg produza uma taxa de quadros diferente. Parece que o mkvmerge / mp4box é necessário, a menos que você possa fazer com que o ffmpeg produza um fluxo de bits .264 bruto e use a opção fps no desmuxador h.264 (que -h documenta totalmente, pois o fluxo de bits não tem tempo informações, apenas encomendar.) #
6264 Peter Cordes
3

Caso sua principal intenção seja reproduzi-lo em câmera lenta, e não manter o arquivo como MP4, você pode usar a ferramenta MKVmerge GUI para remuxá-lo para um contêiner Matroska que pode alterar facilmente a taxa de quadros. Remuxar é muito melhor do que reencodificar, porque apenas altera os metadados, e não o próprio fluxo.

Primeiro você instala o pacote

sudo apt-get install mkvtoolnix-gui

Então você inicia o MKVmerge GUI. Você será confrontado com uma janela como esta

mkvmerge gui 1

Basta pressionar o botão Adicionar e selecionar seu arquivo ou até mesmo arrastar e soltar o arquivo na área "Arquivos de entrada". Nesse ponto, você poderá selecionar o fluxo de vídeo em seu vídeo. Você também pode excluir outros fluxos, pois eles atrapalharão de qualquer maneira.

Depois de selecioná-lo, você verá as guias inferiores se tornando ativas:

insira a descrição da imagem aqui

Mude para "Formatar ações específicas"

insira a descrição da imagem aqui

Você pode ver que existe um campo "FPS", no qual é possível inserir o valor de quadros por segundo. Parecia que você estava planejando desacelerar as coisas quatro vezes, então cerca de 7 quadros por segundo seria o seu objetivo. Você também pode usar a opção "Esticar por".

Depois disso, você pode alterar o nome do arquivo de saída (se desejar) e pressionar "Iniciar muxing".

O programa será executado e você deverá ter seu arquivo.

v010dya
fonte
2

Eu também queria diminuir a velocidade dos meus filmes de 120 FPS para 30 FPS. Eu criei um script que faz isso alterando o andamento do som e modificando o FPS diretamente no contêiner MP4. As seguintes ferramentas são necessárias:

  1. avconv para converter fluxos de áudio
  2. estiramento para diminuir o andamento do áudio
  3. gpac para fazer com que o MP4Box mude o FPS

O script usado para a conversão está aqui:

#!/bin/bash
#########################################
# Lossless slow down from 120 to 30 FPS #
#                                       #
# Use:                                  #
#                                       #
#   slow.bash <mp4_file>                #
#                                       #
#                           #-= OSi =-# #
#########################################


# Prepare basic variables
IN_FILE="$1"
NAME=$(echo "${IN_FILE}" | sed 's/\.[^.]*//')


# Clean up before start
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264" "${NAME}_slow.mp4"


# Slow down sound
avconv -i "${IN_FILE}" -vn -acodec pcm_s16le "${NAME}_.wav"
soundstretch "${NAME}_.wav" "${NAME}.wav" -tempo=-75
avconv -i "${NAME}.wav" -vn -codec:a ac3_fixed -b:a 448k "${NAME}.ac3"


# Change video frame rate and multiplex with slowed sound
MP4Box -add "${IN_FILE}#video" -raw 1 -new "${NAME}"
MP4Box -add "${NAME}_track1.h264:fps=30" -add "${NAME}.ac3" -new "${NAME}_slow.mp4"


# Clean up when we are done
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264"

Este script cria uma cópia do MP4 com _slow postfix.

OSi
fonte