Converti un video in una dimensione dello schermo fissa ritagliandolo e ridimensionandolo


22

Ho provato a capirlo da solo, ma la miriade di opzioni mi sconcerta.

Voglio usare idealmente o ffmpego mencoder(o qualcos'altro, ma quei due che so di aver funzionato) per convertire qualsiasi video in arrivo in una dimensione dello schermo fissa.

Se il video è più largo o troppo corto, quindi ritaglia il video al centro. Se non ha le dimensioni giuste, ridimensiona verso l'alto o verso il basso per renderle esattamente le dimensioni fisse dello schermo.

L'ultima cosa di cui ho bisogno è 720x480 in un AVI XVid con una traccia audio MP3.

Ho trovato molte pagine che mostrano come ridimensionare alla massima risoluzione, ma ho bisogno che il video sia esattamente quella risoluzione (con parti extra tagliate, senza barre nere).

Qualcuno può dirmi la riga di comando da eseguire - o almeno portarmi un po '/ la maggior parte del modo lì? Se deve essere più righe di comando (esegui X per ottenere la risoluzione, esegui questo calcolo e quindi esegui Y con l'output di quel calcolo) Posso scriverlo.


Apparentemente il dispositivo video funziona con Mpeg4 e XVid AVI, se è più facile / migliore.
Andy Jeffries,

Risposte:


19

Non sono un guru di ffmpeg, ma questo dovrebbe fare il trucco.

Prima di tutto, puoi ottenere le dimensioni del video di input in questo modo:

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

Con un ffmpeg abbastanza recente, puoi ridimensionare il tuo video con queste opzioni:

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

È possibile impostare la larghezza o l'altezza su -1per consentire il ffmpegridimensionamento del video mantenendo le proporzioni. In realtà, -2è una scelta migliore poiché il valore calcolato dovrebbe anche. Quindi puoi digitare:

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

Una volta ottenuto il video, potrebbe essere più grande del previsto 720x480poiché hai permesso di ffmpegcalcolare l'altezza, quindi dovrai ritagliarlo. Questo può essere fatto in questo modo:

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

Infine, potresti scrivere uno script come questo (può essere facilmente ottimizzato, ma l'ho mantenuto semplice per leggibilità):

#!/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}

Ho avuto questa strana sensazione che mi sarebbe mancato uno scenario, ma l'ho provato con un sacco di file video e sembra ritagliare e ridimensionare correttamente i video alla dimensione corretta assoluta - ben fatto!
Andy Jeffries,

sembra che ci sia qualcosa di sbagliato nella decisione CROP_SIDE.
Sutra,

`# Ottieni il rapporto tra dimensione effettiva e desiderata w_rate = echo "scale=3; ${in_width}/${out_width}*1000"| bc | awk '{printf "%d", $0}' h_rate = echo "scale=3; ${in_height}/${out_height}*1000"| bc | awk '{printf "%d", $0}' # Prendiamo il lato più corto, quindi il video sarà almeno # grande come la dimensione desiderata, e ritaglia il lato più lungo: crop_side = 'n' se [$ {w_rate} -gt $ {h_rate}]; then scale = "- 2: $ {out_height}" crop_side = 'w' else scale = "$ {out_width}: - 2" crop_side = 'h' fi `
Sutra,

23
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

Sostituisci "input.file" con il nome del tuo file di input.


Questa dovrebbe essere la risposta migliore in quanto non richiede una chiamata a ffprobe. Nota le sequenze di virgole rovesciate nel comando. Dovrai evitare le barre rovesciate se stai inserendo il comando in una stringa C / JavaScript / PHP.
Cleong

Bene, Brian. Anche la parte del filtro video è esattamente ciò di cui avevo bisogno. (ad esempio per convertire i vecchi video 4: 3 in 16: 9)!
Dave,

1
genio! tutto fatto in uno.
Soli,

2
Molto più pulito della sceneggiatura sopra. Nota se non vuoi XVID / MP3 puoi semplicemente cambiare i tag dopo la seconda virgoletta in qualcosa del genere-c:a copy scaled_result.mp4
Nick

7

Se vuoi ritagliare e ridimensionare in una volta sola, puoi creare una catena di filtri ritagliata quindi ridimensiona in questo modo:

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

Quanto sopra prima ritaglia un video in formato 16: 9, quindi ridimensiona fino a 400 px x la larghezza appropriata (numero pari).


1

Sono nuovo di ffmpeg ma ora ho un piccolo convertitore in VB.NET che crea filmati non elaborati di vari formati di output da utilizzare in piccoli dispositivi con accesso alla scheda SD ma non abbastanza per decodificare video complessi.

A causa del modo in cui funziona durante il ridimensionamento e il ritaglio, ho dovuto codificarlo manualmente e creare i parametri. Fondamentalmente ho bisogno di conoscere la larghezza e l'altezza risultanti.

Ho 2 caselle di controllo per le opzioni: -

Mantieni proporzioni (X) Riempi tutti i pixel (X)

Sono necessarie solo 4 variabili come input (1) Larghezza video originale, (2) Altezza video originale, (3) Larghezza dispositivo, (4) Altezza dispositivo.

Sebbene per VB.NET possa essere adattato abbastanza facilmente per qualsiasi lingua.

    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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.