MKV'den MP4'e kod yazma komut dosyası sorunları


1

Tamam, bu benim başımı tırmalamamı sağladı - özellikle bir komut dosyası kullanıcısı olduğum için ve * nix deneyimim en azını söylemek temeldir.

özet

Dolgu maddelerini bir ortam kapsayıcısından diğerine dönüştürmek için kullanılan kabuk komut dosyasının neden hata ve sorun ürettiğini tanımlamanız gerekir.

Senaryo

Bir arkadaş tarafından sağlanan bir kabuk betiği var. Betik, MKV video dosyalarını MP4'e (MPEG-4) dönüştürmek için Ubuntu 10.10 makinelerinde kullanılır. Söz konusu senaryo aşağıdaki gibidir (yorum yapmamayı bağışlayın):

#!/usr/bin/env bash

if [ -f $1 ] ; then
    filename=$(basename $1)
    extension=${filename##*.}
    name=${filename%.*}
    fname=$1
    video=`mediainfo --Inform=Video\;%ID% "${fname}"`
    audio=`mediainfo --Inform=Audio\;%ID% "${fname}"`
    fps=`mediainfo --Inform=Video\;%FrameRate% "${fname}"`
    `mkvextract tracks ${fname} 1:${name}.h264 2:${name}.ac3`
    `a52dec ${name}.ac3 -o wavdolby > ${name}.wav`
    `faac ${name}.wav -o ${name}.m4a`
    `MP4Box -add ${name}.m4a -add ${name}.h264 -fps $fps ${name}.mp4`
    `rm ${name}.m4a ${name}.ac3 ${name}.h264 ${name}.wav`
fi

Sorun

a52dec çalışırken hataları atla

İlk hata yalnızca seçilen MKV dosyalarında meydana gelir; burada ses dönüştürme işleminin bir parçası olarak a52dec'i çalıştırmaya gider.

Meydana gelen bir atlama hatası, konsol / terminal penceresinde tekrar tekrar görünmeye devam ediyor. A52dec işlemi beklenen dosya adını (dosyaadı.wav) oluşturdu, ancak bu atlama iletilerini oluşturmaya devam ediyor ve daha fazla ilerlemiyor (bir sorunun yarısında sadece sorunun geçip geçmeyeceğini görmek için bir saatte yarım saat kalmasına rağmen)

Birkaç farklı dosyadaki Mediainfo çıktısına bakıldığında, dosyanın 5.1 kanal ses içerdiği yerlerde işler sıkışmış gibi görünüyor. Elbette bu sorunun nasıl üstesinden geleceğime dair hiçbir fikrim yok.

IsoMedia: komutu bulunamadı

Bu, betiğin çalışmasını bitirdiğinde her zaman olur, bu n00b'ye göre, söz konusu uygulamayı bulamadığını gösterir.

Ancak, bu paketi bulamıyorum veya hangisinin daha büyük bir paketin parçası olacaksa bulamıyorum.

Daha da kafa karıştırıcı olan bu dosya, komut dosyası sırasında herhangi bir noktada çağrılmaz ve yalnızca temizlemek için rm komutunun çalıştırılmasından sonra çağrılır.

Fazladan bilgi

Sorunsuz kodlar bir MKV dosyası için Mediainfo çıktısı örneği

General
Unique ID                        : 233323168834975742075458986504469215458 (0xAF886862D1B0BB1B9427E04C90A1F8E2)
Complete name                    : \\192.168.2.5\video\sorted\CSI NY\CSI.New.York.S07E10.720p.HDTV.X264-DIMENSION.mkv
Format                           : Matroska
File size                        : 1.09 GiB
Duration                         : 41mn 30s
Overall bit rate                 : 3 768 Kbps
Encoded date                     : UTC 2010-12-03 20:40:51
Writing application              : mkvmerge v3.1.0 ('Happy up here') built on Jan 19 2010 12:09:24
Writing library                  : libebml v0.7.9 + libmatroska v0.8.1

Video
ID                               : 1
Format                           : AVC
Format/Info                      : Advanced Video Codec
Format profile                   : High@L4.1
Format settings, CABAC           : Yes
Format settings, ReFrames        : 8 frames
Format settings, GOP             : M=6, N=12
Codec ID                         : V_MPEG4/ISO/AVC
Duration                         : 41mn 30s
Bit rate                         : 3 381 Kbps
Width                            : 1 280 pixels
Height                           : 720 pixels
Display aspect ratio             : 16:9
Frame rate                       : 23.976 fps
Color space                      : YUV
Chroma subsampling               : 4:2:0
Bit depth                        : 8 bits
Scan type                        : Progressive
Bits/(Pixel*Frame)               : 0.153
Stream size                      : 982 MiB (88%)
Writing library                  : x264 core 110 r1804 e89c4cf
Encoding settings                : cabac=1 / ref=8 / deblock=1:0:0 / analyse=0x3:0x113 / me=umh / subme=9 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=0 / chroma_qp_offset=-2 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / constrained_intra=0 / bframes=5 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=23 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=2pass / mbtree=1 / bitrate=3381 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=51 / qpstep=4 / cplxblur=20.0 / qblur=0.5 / ip_ratio=1.40 / aq=1:1.00
Language                         : English

Audio
ID                               : 2
Format                           : AC-3
Format/Info                      : Audio Coding 3
Mode extension                   : CM (complete main)
Codec ID                         : A_AC3
Duration                         : 41mn 30s
Bit rate mode                    : Constant
Bit rate                         : 384 Kbps
Channel(s)                       : 2 channels
Channel positions                : Front: L R
Sampling rate                    : 48.0 KHz
Bit depth                        : 16 bits
Compression mode                 : Lossy
Stream size                      : 114 MiB (10%)

A52dec sorunlarına neden olan bir MKV dosyası için Mediainfo çıktısı örneği

General
Unique ID                        : 173353892635048029459501626055714892286 (0x826ABECAAEC6D2638DD0EC376D6369FE)
Complete name                    : \\192.168.2.5\video\sorted\Conan\conan.2010.11.25.jim.parsons.720p.hdtv.x264-bff.mkv
Format                           : Matroska
File size                        : 1.09 GiB
Duration                         : 42mn 1s
Overall bit rate                 : 3 720 Kbps
Encoded date                     : UTC 2010-11-26 05:45:43
Writing application              : mkvmerge v3.1.0 ('Happy up here') built on Jan 19 2010 12:09:24
Writing library                  : libebml v0.7.9 + libmatroska v0.8.1

Video
ID                               : 2
Format                           : AVC
Format/Info                      : Advanced Video Codec
Format profile                   : High@L3.1
Format settings, CABAC           : Yes
Format settings, ReFrames        : 3 frames
Codec ID                         : V_MPEG4/ISO/AVC
Duration                         : 42mn 1s
Bit rate                         : 3 272 Kbps
Width                            : 1 280 pixels
Height                           : 720 pixels
Display aspect ratio             : 16:9
Frame rate                       : 29.970 fps
Color space                      : YUV
Chroma subsampling               : 4:2:0
Bit depth                        : 8 bits
Scan type                        : Progressive
Bits/(Pixel*Frame)               : 0.118
Stream size                      : 961 MiB (86%)
Writing library                  : x264 core 85 r1442tw
Encoding settings                : cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=6 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=30 / sliced_threads=0 / nr=0 / decimate=1 / mbaff=0 / constrained_intra=0 / bframes=6 / b_pyramid=1 / b_adapt=1 / b_bias=0 / direct=1 / wpredb=1 / wpredp=0 / keyint=240 / keyint_min=24 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=2pass / mbtree=1 / bitrate=3272 / ratetol=1.0 / qcomp=0.60 / qpmin=10 / qpmax=51 / qpstep=4 / cplxblur=20.0 / qblur=0.5 / ip_ratio=1.40 / aq=1:1.00
Language                         : English

Audio
ID                               : 1
Format                           : AC-3
Format/Info                      : Audio Coding 3
Mode extension                   : CM (complete main)
Codec ID                         : A_AC3
Duration                         : 42mn 1s
Bit rate mode                    : Constant
Bit rate                         : 448 Kbps
Channel(s)                       : 6 channels
Channel positions                : Front: L C R, Side: L R, LFE
Sampling rate                    : 48.0 KHz
Bit depth                        : 16 bits
Compression mode                 : Lossy
Stream size                      : 135 MiB (12%)

Ffmpeg kullanmayı denediniz mi?
Merhaba71

@ Merhaba71: Bu sadece bir düşünceye yol açtı ve ben de cevabımı buldum. Teşekkürler.
thewinchester

Yanıtlar:


3

MKV MP4 Remuxing Script

Bu, Winchester'ın buradaki cevabında yazan senaryosuna dayanıyor . Onunla başladım ve sonunda çoğunu tekrar yazdı, ama kavram aynı.

Temel işlev, h.264 video ve bir miktar ses içeren bir MKV dosyası almak ve onu bir MP4 / M4V dosyasına dönüştürmektir.

Amacım, çıkan dosyaları iPad ve AppleTV ile uyumlu hale getirmektir, ancak MP4 / M4V dosyalarını işleyebilecek herhangi bir şeyle çalışması gerekir. Video kodlanmış değildir, bu nedenle kalite aynı kalır, gerekirse ses dönüştürülür, ancak mümkünse daha yüksek kaliteli parçalar tutulur.

değişiklikler

Yaptığım değişikliklerin kısmi bir listesi:

  • Argüman olarak iletilen birden fazla dosyayı veya klasörü kullanma
  • AC3 veya DTS’den AAC sesi kodlamak için daha yüksek kaliteli NeroAAC kullanır (ve gerektirir)
  • AppleTV'de düzgün çalma ve surround ses sağlamak için birden fazla ses parçasını AppleTV standardına uygun olarak kullanmak:
    • 160kB / s stereo AAC
    • (İsteğe bağlı) AC-3 (tipik olarak surround ses) ikinci parça olarak devre dışı
  • DTS'yi AC-3'e dönüştürme
  • Siparişten bağımsız olarak birden fazla parçanın kullanılması (örn. AAC, Video, AC3)
  • Daha sonra değiştirmeyi kolaylaştırmak için çeşitli kodlama değişiklikleri

Gereksinimler

Betik yukarıda belirtilen NeroAAC'in yanı sıra Aften (AC3 kodlama) ve libdca / dcadec (DTS kod çözme) gerektirir. Orijinal komut dosyasında olduğu gibi, ffmpeg de gereklidir.

Bilinen Sorunlar

Senaryo oldukça kurşun geçirmez - başa çıkamayacağı bir şeye rastlarsa, genellikle göz ardı edilir veya çıkar. Orijinal dosyalar bozulmadan kalır, bu nedenle veri kaybı için çok az veya hiç şans yoktur.

Medya kitaplığımın çoğunda kullandım ve değişikliklerin çoğu karşılaştığım hataları düzeltmek için yapıldı.

Bununla birlikte, dikkat edilmesi gereken birkaç şey var ve iyileştirme için yer var:

  • Aynı türden birden fazla ses parçasını kullanma - 1 AC3 ve 1 AAC iyi, ancak 2 AAC parça işe yaramaz. Bu sık sık ortaya çıkmamalı, fakat aklınızda bulundurun.
  • Ses / video parçaları için destek yok. Altyazılar, bölümler ve sanat eserleri göz ardı edilir.
  • Surround ses algılaması yok AAC. Betik, herhangi bir AAC parçasını kopyalar, stereo'ya karıştırmaz. Teknik olarak iPad ve AppleTV desteği için, ana ses parçasının stereo AAC olması gerekir , ancak çoğu durumda bir iPad veya AppleTV'nin zarifçe kullanabileceğini düşünüyorum.

Kod ve kullanım

Birisinin yararlı bulmasını umarak buraya gönderiyorum - lütfen ticari olmayan kullanımlara uygun olduğunu düşündüğünüz gibi kullanmaktan ve değiştirmekten çekinmeyin. İlginç bir değişiklik yaparsanız, burada ya da başka bir yerde paylaşmanız güzel olurdu.

#!/bin/bash

#Close stdin - avoid accidental keypresses causing problems
exec 0>&-

# Find MKV files
for file in "$@";
do
  find "$file" -type f -not -name ".*" | grep .mkv$ | while read file
  do
    fileProper=$(readlink -f "$file") # full path of file
    pathNoExt=${fileProper%.*} # full path minus extension

    #Check if M4V already exists
    if [ -f "$pathNoExt".m4v ]; then
      echo "M4V already exists, stopping"
    else
      # Get number of tracks
      numberOfTracks=`mkvmerge -i "$fileProper" | grep "Track ID" | wc -l`
      echo "Found $numberOfTracks Tracks"

      # Set base extraction command
      extractCmd+=(mkvextract tracks "$fileProper")

      # Determine type of tracks
      for (( i=1; i<=$numberOfTracks; i++ ))
      do
         trackType=`mkvmerge -i "$fileProper" | grep "Track ID $i" | sed -e 's/^.*: //'`
         if [[ "$trackType" == *video* ]]; then
            echo "Track $i is Video"
            extractCmd+=( $i:"$pathNoExt".264)
            fps=`mkvinfo "$fileProper" | grep duration | sed -e 's/.*(//' -e 's/f.*//' | sed -n ${i}p`
         elif [[ "$trackType" == "audio (A_AAC)" ]]; then
            echo "Track $i is AAC"
            extractCmd+=( $i:"$pathNoExt".aac)
         elif [[ "$trackType" == "audio (A_AC3)" ]]; then
            echo "Track $i is AC3"
            extractCmd+=( $i:"$pathNoExt".ac3)
         elif [[ "$trackType" == "audio (A_DTS)" ]]; then
            echo "Track $i is DTS"
            extractCmd+=( $i:"$pathNoExt".dts)
         fi
         # Insert cases for handling other audio and non-AV tracks here
       done

        "${extractCmd[@]}" # Extract Tracks

        # Check files and encode audio if neccessary
        if [ -f "$pathNoExt".264 ]; then
            # Video file exists
            mp4BoxCmd+=(MP4Box -new "$pathNoExt".m4v -add "$pathNoExt".264 -fps $fps)
            if [ -f "$pathNoExt".aac ]; then
                # AAC exists
                mp4BoxCmd+=( -add "$pathNoExt".aac)
                if [ -f "$pathNoExt".ac3 ]; then
                    mp4BoxCmd+=( -add "$pathNoExt".ac3:disable)
                elif [ -f "$pathNoExt".dts ]; then
                    # Encode DTS to AC3
                    dcadec -o wavall "$pathNoExt".dts | aften -v 0 - "$pathNoExt".ac3
                    mp4BoxCmd+=( -add "$pathNoExt".ac3:disable)
                fi
            else # Encode AAC from AC3 or DTS
                if [ -f "$pathNoExt".ac3 ]; then
                    ffmpeg -i "$pathNoExt".ac3 -acodec pcm_s16le -ac 2 -f wav - | neroAacEnc -lc -br 160000 -ignorelength -if - -of "$pathNoExt".aac
                    mp4BoxCmd+=( -add "$pathNoExt".aac -add "$pathNoExt".ac3:disable)
                elif [ -f "$pathNoExt".dts ]; then
                  ffmpeg -i "$pathNoExt".dts -acodec pcm_s16le -ac 2 -f wav - | neroAacEnc -lc -br 160000 -ignorelength -if - -of "$pathNoExt".aac
                    # Encode DTS to AC3
                    dcadec -o wavall "$pathNoExt".dts | aften -v 0 - "$pathNoExt".ac3
                    mp4BoxCmd+=( -add "$pathNoExt".aac -add "$pathNoExt".ac3:disable)
                else
                    echo "Warning: no audio file found"
                fi
            fi
            # Create m4v
            "${mp4BoxCmd[@]}"
        else
            echo "Error: no video file found"
        fi
  #remove temporary track files
  rm -f "$pathNoExt".aac "$pathNoExt".dts "$pathNoExt".ac3 "$pathNoExt".264 "$pathNoExt".wav
  fi
 done
done

Hey, biraz değiştirilmiş bir versiyonunu öz olarak yayınlayabilir miyim?
T0xicCode

Tabii, buraya bağlarsan memnun olurum. En son güncellendiğimden beri de bazı değişiklikler yaptım ve etiketlemek için github ya da başka bir şey koymak için anlam ifade ettiğim, ancak bununla ilgili bir şeyler yapmadığım bir sürü kod yazdım.
robmathers

İşte başlıyoruz : öz: 3433942
T0xicCode

1

Merhaba71, ffmpeg yorumuyla bir düşünce başlattı ve cevabımı ek bir aramadan sonra buldum .

Dosyayı dönüştürmek için başarılı kodun bir kopyası aşağıdaki gibidir. Garip bir ses formatı kullanıldığında ayrıca biraz daha incelikli bir şekilde başarısız olur.

(Anlaşmayı kolaylaştırmak için yorumlar eklendi)

#!/bin/bash


# Evaluate the file passed to the script for information relevant to the process
find . -type f | grep .mkv$ | while read file
do
directory=`dirname "$file"`
title=`basename "$file" .mkv`

# Check the audio track used in the files
AC3=`mkvinfo "$file" | grep AC3` #check if it's AC3 audio or DTS
AAC=`mkvinfo "$file" | grep AAC`
order=`mkvinfo "$file" | grep "Track type" | sed 's/.*://' | head -n 1 | tr -d " "` #check if the video track is first or the audio track

# Start processing
# If video is the first track
if [ "$order" = "video" ]; then
  fps=`mkvinfo "$file" | grep duration | sed 's/.*(//' | sed 's/f.*//' | head -n 1` #store the fps of the video track

# If audio is encoded in AC3
  if [ -n "$AC3" ]; then
   mkvextract tracks "$file" 1:"${title}".264 2:"${title}".ac3
   ffmpeg -i "${title}".ac3 -acodec libfaac -ab 576k "${title}".aac
#  mplayer -ao pcm:file="${title}".wav:fast "${title}".ac3
#  faac -o "${title}".aac "${title}".wav


# If audio is encoded in AAC
  elif [ -n "$AAC" ]; then
   mkvextract tracks "$file" 1:"${title}".264 2:"${title}".aac

# If encoded in DTS or something else
  else
   mkvextract tracks "$file" 1:"${title}".264 2:"${title}".dts
   ffmpeg -i "${title}".dts -acodec libfaac -ab 576k "${title}".aac
  fi
else

# If video is not the first track
  fps=`mkvinfo "$file" | grep duration | sed 's/.*(//' | sed 's/f.*//' | tail -n 1`
  if [ -n "$AC3" ]; then
   mkvextract tracks "$file" 1:"${title}".ac3 2:"${title}".264
   ffmpeg -i "${title}".ac3 -acodec libfaac -ab 576k "${title}".aac
  # mplayer -ao pcm:file="${title}".wav:fast "${title}".ac3
  # faac -o "${title}".aac "${title}".wav
  elif [ -n "$AAC" ]; then
   mkvextract tracks "$file" 1:"${title}".264 2:"${title}".aac
  else
   mkvextract tracks "$file" 1:"${title}".dts 2:"${title}".264
   ffmpeg -i "${title}".dts -acodec libfaac -ab 576k "${title}".aac
  fi
fi
MP4Box -new "${directory}/${title}".mp4 -add "${title}".264 -add "${title}".aac -fps $fps
rm -f "$title".aac "$title".dts "$title".ac3 "$title".264 "${title}".wav
# if [ -f "${directory}/${title}".mp4 ]; then
# rm -f "$file"
# fi
done

Sadece bunun için bir ton teşekkür etmek istedim. Bir ya da iki ay önce karşılaştı ve tam olarak aradığım buydu. Yaptığım şeyi uyacak şekilde değişiklik ve iyileştirmeler yapmak için yavaşça çalışıyordum. Versiyonumu bu soruya ayrı bir cevap olarak göndereceğim, umarım birileri sizinkileri bulduğum kadar faydalı bulur.
Robmaters

1

FFmpeg aracı burada açıklananların çoğunu yapabilir.

ffmpeg -i input.mkv -c copy output.mp4

Bir for döngüsünde (bir dizindeki her * .mkv dosyasını remux):

for f in *.mkv; do ffmpeg -i "$f" -c copy "${f/%mkv/mp4}"; done

... çoğu zaman çalışacaktır, çünkü çoğu MKV dosyası h.264 video ve AAC ses sistemine sahip olacaktır. Bunları kullanmayan bir dosyayı dönüştürmek için:

ffmpeg -i input.mkv -c:v libx264 -crf 23 -preset veryfast -c:a libfdk_aac -vbr 3 output.mp4

Daha fazla bilgi için FFmpeg wiki'deki x264 ve AAC kodlama kılavuzlarına bakın .

Yalnızca kesinlikle dönüştürülmesi gereken dosyaları dönüştürmek istiyorsanız, böyle bir bash betiği kullanabilirsiniz:

#!/bin/bash
for f in *.mkv
do

##  Detect what audio codec is being used:
audio=$(ffprobe "$f" 2>&1 | sed -n '/Audio:/s/.*: \([a-zA-Z0-9]*\).*/\1/p' | sed 1q)
##  Detect video codec:
video=$(ffprobe "$f" 2>&1 | sed -n '/Video:/s/.*: \([a-zA-Z0-9]*\).*/\1/p' | sed 1q)
##  Set default audio settings (you may need to use a different encoder,
##  since libfdk_aac is not re-distributable)
aopts="-c:a libfdk_aac -vbr 3"
##  Set default video settings:
vopts="-c:v libx264 -crf 22 -preset veryfast"

    case "$audio" in
        aac|alac|mp3|mp2|ac3 )
##  If the audio is one of the MP4-supported codecs,
##  copy the stream instead of transcoding
            aopts="-c:a copy"
            ;;
        "" )
##  If there is no audio stream, don't bother with audio
            aopts="-an"
            ;;
        * )
            ;;
    esac

    case "$video" in
##  If the video stream is one of the MP4-compatible formats,
##  copy the stream
        h264|mpeg4|mpeg2video|mpeg1video )
            vopts="-c:v copy"
            ;;
        "" )
## If no video stream is detected, don't bother with video
            vopts="-vn"
            ;;
        * )
            ;;
    esac

##  This will tell you what is going on; that is,
##  it will echo a line that will make the terminal output
##  easier to follow:
echo -e "\n    \E[1;30mffmpeg -i $f -map 0 $vopts $aopts ${f/%mkv/mp4}\E[0m"

##  And now, to the meat of the thing.
##  Normally you should ALWAYS quote your variables
##  so that spaces in filenames etc will be preserved.
##  But in this case, doing so for $vopts and $aopts
##  would break the ffmpeg command
##  because we WANT the spaces to break up the strings:
ffmpeg -y -i "$f" -map 0 $vopts $aopts "${f/%mkv/mp4}"
done

exit 0

Harika şeyler, yapabilseydim +100 olurdu.
slhck,
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.