Converte um vídeo para um tamanho de tela fixo cortando e redimensionando

15

Eu mesmo tentei descobrir isso, mas a miríade de opções me surpreende.

Eu quero usar idealmente ffmpeg ou mencoder (ou qualquer outra coisa, mas os dois que eu sei que estou trabalhando) para converter qualquer vídeo recebido em um tamanho de tela fixo.

Se o vídeo for mais largo ou muito curto, centralize o vídeo. Se não for o tamanho certo, redimensione para cima ou para baixo para torná-lo exatamente o tamanho da tela fixa.

A última coisa que eu preciso é de 720x480 em um XVID AVI com uma faixa de áudio MP3.

Encontrei muitas páginas mostrando como redimensionar para uma resolução máxima, mas preciso que o vídeo tenha exatamente essa resolução (com as partes extras cortadas, sem barras pretas).

Alguém pode me dizer a linha de comando para executar - ou pelo menos me pegar algum / a maior parte do caminho? Se precisar de múltiplas linhas de comando (execute X para obter a resolução, faça este cálculo e, em seguida, execute Y com a saída desse cálculo) Eu posso roteirizar isso.

    
por Andy Jeffries 16.03.2015 / 09:54

4 respostas

15

Eu não sou um guru ffmpeg, mas isso deve funcionar.

Primeiro de tudo, você pode obter o tamanho do vídeo de entrada assim:

ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width in.mp4

Com um ffmpeg razoavelmente recente, você pode redimensionar seu vídeo com estas opções:

ffmpeg -i in.mp4 -vf scale=720:480 out.mp4

Você pode definir a largura ou a altura como -1 para permitir que ffmpeg redimensione o vídeo mantendo a proporção. Na verdade, -2 é a melhor escolha, pois o valor computado deve ser o mesmo. Então você pode digitar:

ffmpeg -i in.mp4 -vf scale=720:-2 out.mp4

Depois que você obtiver o vídeo, ele poderá ser maior do que o esperado 720x480 , já que você deixou ffmpeg computar a altura, então será necessário cortá-lo. Isso pode ser feito assim:

ffmpeg -i in.mp4 -filter:v "crop=in_w:480" out.mp4

Finalmente, você poderia escrever um script como este (pode ser facilmente otimizado, mas eu mantive isso simples para legibilidade):

#!/bin/bash

FILE="/tmp/test.mp4"
TMP="/tmp/tmp.mp4"
OUT="/tmp/out.mp4"

OUT_WIDTH=720
OUT_HEIGHT=480

# Get the size of input video:
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width ${FILE})
IN_WIDTH=${streams_stream_0_width}
IN_HEIGHT=${streams_stream_0_height}

# Get the difference between actual and desired size
W_DIFF=$[ ${OUT_WIDTH} - ${IN_WIDTH} ]
H_DIFF=$[ ${OUT_HEIGHT} - ${IN_HEIGHT} ]

# Let's take the shorter side, so the video will be at least as big
# as the desired size:
CROP_SIDE="n"
if [ ${W_DIFF} -lt ${H_DIFF} ] ; then
  SCALE="-2:${OUT_HEIGHT}"
  CROP_SIDE="w"
else
  SCALE="${OUT_WIDTH}:-2"
  CROP_SIDE="h"
fi

# Then perform a first resizing
ffmpeg -i ${FILE} -vf scale=${SCALE} ${TMP}

# Now get the temporary video size
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width ${TMP})
IN_WIDTH=${streams_stream_0_width}
IN_HEIGHT=${streams_stream_0_height}

# Calculate how much we should crop
if [ "z${CROP_SIDE}" = "zh" ] ; then
  DIFF=$[ ${IN_HEIGHT} - ${OUT_HEIGHT} ]
  CROP="in_w:in_h-${DIFF}"
elif [ "z${CROP_SIDE}" = "zw" ] ; then
  DIFF=$[ ${IN_WIDTH} - ${OUT_WIDTH} ]
  CROP="in_w-${DIFF}:in_h"
fi

# Then crop...
ffmpeg -i ${TMP} -filter:v "crop=${CROP}" ${OUT}
    
por 23.03.2015 / 17:29
16
ffmpeg -i input.file -vf "scale=(iw*sar)*max(720/(iw*sar)\,480/ih):ih*max(720/(iw*sar)\,480/ih), crop=720:480" -c:v mpeg4 -vtag XVID -q:v 4 -c:a libmp3lame -q:a 4 output.avi

Substitua "input.file" pelo nome do seu arquivo de entrada.

    
por 24.03.2015 / 04:34
6

Se você deseja recortar e dimensionar de uma só vez, é possível criar um conjunto de filtros de escala da cultura da seguinte forma:

ffmpeg -i SomeInput.mp4 -vf "crop=in_h*9/16:in_h,scale=-2:400" -t 4 SomeOutput.mp4

O primeiro corta um vídeo em 16: 9 retrato, em seguida, escala para 400px alta x a largura apropriada (número par).

    
por 22.05.2016 / 07:17
1

Sou novo no ffmpeg, mas agora tenho um pequeno conversor em VB.NET que cria filmes raw de vários formatos de saída para uso em pequenos dispositivos que têm acesso ao cartão SD, mas não tem energia suficiente para decodificar vídeo complexo.

Por causa da maneira como funciona ao redimensionar e cortar, eu tive que codificar manualmente e construir os parâmetros. Basicamente eu preciso saber a largura e a altura resultantes.

Eu tenho 2 caixas de seleção para as opções: -

Preserve a proporção (X) Preencha todos os pixels (X)

Apenas 4 variáveis são necessárias como entrada (1) Largura original do vídeo, (2) Altura do vídeo original, (3) Largura do dispositivo, (4) Altura do dispositivo.

Embora o VB.NET possa ser adaptado com facilidade para qualquer idioma.

    Dim crop As String = "" ' will build this in ffmpeg format for -s or scale and crop

    If cbAspectRatio.Checked = False Then
        m_dest_output_w = sz._w
        m_dest_output_h = sz._h

        ' scale to w * h - simple
        crop = " -s " & m_dest_output_w & ":" & m_dest_output_h
    Else
        Dim ratio As Double = CDbl(m_video_width) / CDbl(m_video_height) ' this is aspect ratio of original unsized video

        If cbFillPixels.Checked = False Then ' shrink to fit
            If sz._w * ratio <= m_video_height Then
                m_dest_output_w = sz._w
                m_dest_output_h = sz._w / ratio
            Else
                m_dest_output_h = sz._h
                m_dest_output_w = sz._h / ratio
            End If

            ' no cropping just resizing to a non-filled area that fits

            crop = " -s " & m_dest_output_w & ":" & m_dest_output_h ' no cropping needed as letterboxed

        Else ' expand / fill --- cropping needed
            If sz._w * ratio >= m_video_height Then
                m_dest_output_w = sz._w
                m_dest_output_h = sz._w * ratio

                crop = ",crop=" & sz._w & ":" & sz._h & ":0:" & Math.Abs((m_dest_output_h - sz._h)) \ 2
            Else
                m_dest_output_h = sz._h
                m_dest_output_w = sz._h * ratio

                crop = ",crop=" & sz._w & ":" & sz._h & ":" & Math.Abs((m_dest_output_w - sz._w)) \ 2 & ":0"
            End If

            crop = " -vf scale=" & m_dest_output_w & ":" & m_dest_output_h & crop

            m_dest_output_w = sz._w
            m_dest_output_h = sz._h
        End If
    End If
    
por 10.03.2017 / 19:19