He intentado resolver esto yo mismo, pero la miríada de opciones simplemente me desconcierta.
Lo ideal es utilizar ffmpeg
o mencoder
(o algo más, pero sé que esos dos funcionan ) para convertir cualquier video entrante a un tamaño de pantalla fijo.
Si el video es más ancho o demasiado corto para él, entonces recorte el video en el centro. Si no tiene el tamaño correcto, el cambio de tamaño o para que tenga exactamente el tamaño de pantalla fijo.
Lo último que necesito es 720×480 en un XVid AVI con una pista de audio MP3.
He encontrado muchas páginas que muestran cómo cambiar el tamaño a una resolución máxima, pero necesito que el video tenga exactamente esa resolución (con partes adicionales recortadas, sin barras negras).
¿Alguien puede decirme la línea de comando para ejecutar, o al menos conseguirme un poco / la mayor parte del camino? Si necesita ser varias líneas de comando (ejecute X para obtener la resolución, es el cálculo y luego ejecutar Y con el resultado de ese cálculo) Puedo escribir eso.
Comentarios
- Aparentemente, el dispositivo de video también funciona con Mpeg4 como XVid AVI, si eso ‘ es más fácil / mejor.
Responder
No soy un gurú de ffmpeg, pero esto debería funcionar.
En primer lugar, puede obtener el tamaño del video de entrada de esta manera:
ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width in.mp4
Con un ffmpeg relativamente reciente, puedes cambiar el tamaño de tu video con estas opciones:
ffmpeg -i in.mp4 -vf scale=720:480 out.mp4
Puedes establecer el ancho o el alto a -1
para permitir ffmpeg
cambiar el tamaño del video manteniendo la relación de aspecto. En realidad, -2
es una mejor opción ya que el valor calculado debería ser par. Entonces, podría escribir:
ffmpeg -i in.mp4 -vf scale=720:-2 out.mp4
Una vez que obtenga el video, puede ser más grande que el 720x480
esperado ya que Dejas que ffmpeg
calcule la altura, así que tendrás que recortarla. Esto se puede hacer así:
ffmpeg -i in.mp4 -filter:v "crop=in_w:480" out.mp4
Finalmente, podría escribir un script como este (se puede optimizar fácilmente, pero lo mantuve simple para que sea legible):
#!/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}
Comentarios
- Tuve la extraña sensación de que ‘ me perdí un escenario, pero yo ‘ Lo he probado con un montón de archivos de video y parece recortar y redimensionar correctamente los videos al tamaño absolutamente correcto. ¡Bien hecho!
- Parece que hay algún error en la decisión CROP_SIDE.
- `# Obtenga la tasa entre el tamaño real y el deseado 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}'
# Let ‘ s toma el lado más corto, por lo que el video será al menos tan grande # como el tamaño deseado y recorta el lado más largo: crop_side = ‘ n ‘ if [$ {w_rate} -gt $ {h_rate}]; luego scale = » -2: $ {out_height} » crop_side = ‘ w ‘ else scale = » $ {out_width}: – 2 » crop_side = ‘ h ‘ fi `
Responder
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
Reemplace» input.file «con el nombre de su archivo de entrada.
Comentarios
- Esta debería ser la respuesta principal, ya que no ‘ no requiere una llamada a ffprobe. Tenga en cuenta las secuencias de comas con barra invertida en el comando. ‘ necesitará escapar de las barras diagonales inversas si ‘ está colocando el comando en una cadena C / JavaScript / PHP.
- Bien, Brian. La parte del filtro de video es exactamente lo que necesitaba también. (es decir, convertir videos antiguos de 4: 3 a 16: 9).
- ¡Genial! todo hecho en uno.
- Mucho más limpio que el script anterior. Tenga en cuenta que si no ‘ no desea XVID / MP3, puede cambiar las etiquetas después de la segunda comilla por algo como
-c:a copy scaled_result.mp4
- ¿puedes explicarme qué ‘ s
sar
dentro deiw*sar
Respuesta
Si desea recortar y escalar de una sola vez, puede crear una cadena de filtros para recortar y luego escalar así:
ffmpeg -i SomeInput.mp4 -vf "crop=in_h*9/16:in_h,scale=-2:400" -t 4 SomeOutput.mp4
Lo anterior primero recorta un video en retrato 16: 9, luego lo escala a 400 px de alto x el ancho apropiado (número par).
Respuesta
Soy nuevo en ffmpeg pero ahora tengo un pequeño convertidor en VB.NET que crea películas sin procesar de varios formatos de salida para usar en dispositivos pequeños que tienen acceso a la tarjeta SD pero no tienen suficiente potencia para decodificar videos complejos.
Debido a la forma en que funciona al cambiar el tamaño y recortar, tuve que codificarlo manualmente y construir los parámetros. Básicamente necesito saber el ancho y alto resultantes.
Tengo 2 casillas de verificación para las opciones: –
Conservar relación de aspecto (X) Rellenar todos los píxeles (X)
Solo se necesitan 4 variables como entrada (1) Ancho del video original, (2) Alto del video original, (3) Ancho del dispositivo, (4) Alto del dispositivo.
Aunque para VB.NET podría adaptarse bastante fácilmente a cualquier 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