Bir videoyu kırparak ve yeniden boyutlandırarak sabit ekran boyutuna dönüştürme


22

Bunu kendim anlamaya çalıştım, ama sayısız seçenek beni şaşırtıyor.

Herhangi bir gelen videoyu sabit ekran boyutuna dönüştürmek için ideal olarak ya ffmpegda mencoder(veya başka bir şey, ama çalıştığımı bildiğim bu ikisi) kullanmak istiyorum.

Video daha geniş veya çok kısaysa videoyu ortada kırpın. Doğru boyutta değilse, tam olarak sabit ekran boyutunu yapmak için yeniden boyutlandırın veya yeniden boyutlandırın.

İhtiyacım olan kesin şey, bir MP3 ses parçasına sahip bir XVid AVI'de 720x480.

Maksimum çözünürlüğe nasıl yeniden boyutlandırılacağını gösteren birçok sayfa buldum, ancak videonun tam olarak bu çözünürlükte olması gerekiyor (ekstra parçalar kırpılmış, siyah çubuklar yok).

Birisi bana komut satırını çalıştırmamı söyleyebilir - ya da en azından bana oradan bir / çoğunu alabilir mi? Birden fazla komut satırı olması gerekiyorsa (çözünürlüğü almak için X'i çalıştırın, bu hesaplamayı yapın ve sonra o hesaplamanın çıktısıyla Y'yi çalıştırın) Bunu komut dosyası yapabilirim.


Görünüşe göre video cihazı daha kolay / daha iyi ise Mpeg4 ve XVid AVI ile çalışır.
Andy Jeffries

Yanıtlar:


19

Ben ffmpeg gurusu değilim, ama bu hile yapmalı.

Her şeyden önce, giriş videosunun boyutunu aşağıdaki gibi alabilirsiniz:

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

Oldukça yeni bir ffmpeg ile videonuzu aşağıdaki seçeneklerle yeniden boyutlandırabilirsiniz:

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

Sen hiç genişliği veya yüksekliği ayarlayabilirsiniz -1bırakılması için ffmpegboy oranını koruyarak videoyu yeniden boyutlandırmak. Aslında, -2hesaplanan değerin eşit olması gerektiğinden daha iyi bir seçimdir. Böylece şunu yazabilirsiniz:

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

Videoyu aldıktan sonra , yüksekliği hesaplamanıza 720x480izin verdiğinizden beklenenden daha büyük olabilir ffmpeg, bu nedenle kırpmanız gerekir. Bu şu şekilde yapılabilir:

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

Son olarak, böyle bir komut dosyası yazabilirsiniz (kolayca optimize edilebilir, ancak okunabilirlik için basit tuttum):

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

Bir senaryoyu kaçırdığı gibi komik bir duygum vardı, ancak bir sürü video dosyasıyla denedim ve videoları doğru bir şekilde kırpıp yeniden boyutlandırıyor gibi görünüyor - aferin!
Andy Jeffries

CROP_SIDE kararında bazı yanlışlar var gibi görünüyor.
Sutra

`# Gerçek ve istenen boyut arasındaki oranı alın 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}' # Daha kısa tarafını alalım, böylece video en az istenen boyutta # kadar büyük olacak ve daha uzun tarafı kırpacaktır: crop_side = 'n' if [$ {w_rate} -gt $ {h_rate}]; ardından 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

"İnput.file" yerine girdi dosyanızın adını yazın.


Bu en iyi yanıt olmalıdır çünkü ffprobe çağrısı gerektirmez. Komuttaki ters eğik çizgi virgül dizilerini not edin. Komutu bir C / JavaScript / PHP dizesine yerleştiriyorsanız ters eğik çizgilerden kaçmanız gerekir.
cleong

Güzel, Brian. Video filtre kısmı da tam olarak ihtiyacım olan şey. (yani eski 4: 3 videoları 16: 9'a dönüştürmek için)!
Dave

1
deha! hepsi bir arada yapılır.
Soli

2
Yukarıdaki komut dosyası çok daha temiz. Eğer XVID / MP3 istemiyorsanız, sadece ikinci tırnak işaretinden sonra etiketleri aşağıdaki gibi değiştirebilirsiniz-c:a copy scaled_result.mp4
Nick

7

Bir seferde kırpmak ve ölçeklemek istiyorsanız, böyle bir kırpma-sonra-ölçekli filtre zinciri yapabilirsiniz:

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

Yukarıdaki ilk önce bir videoyu 16: 9 resme kırpıyor, sonra 400 piksel yüksekliğe x uygun (çift sayı) genişliğe ölçekleniyor.


1

Ben ffmpeg için yeniyim ama şimdi SD kart erişimi olan ancak karmaşık video kodunu çözmek için yeterli güç olmayan küçük cihazlarda kullanılmak üzere çeşitli çıkış formatlarının ham filmlerini oluşturan VB.NET'e giden güzel bir küçük dönüştürücü var.

Yeniden boyutlandırma ve kırpma sırasında çalışma şekli nedeniyle manuel olarak kodlamak ve parametreleri oluşturmak zorunda kaldı. Temelde ortaya çıkan genişlik ve yüksekliği bilmem gerekiyor.

Seçenekler için 2 onay kutum var: -

En Boy Oranını Koru (X) Tüm Pikselleri Doldur (X)

Giriş (1) Orijinal video genişliği, (2) Orijinal video yüksekliği, (3) Cihaz genişliği, (4) Cihaz yüksekliği olarak yalnızca 4 değişken gereklidir.

Her ne kadar VB.NET için herhangi bir dil için oldukça kolay adapte edilebilir.

    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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.