1

Хорошо, это заставило меня почесать голову - тем более, что я пишу сценарий nOOb, и мой опыт * nix является базовым, если не сказать больше.

Резюме

Необходимо определить, почему сценарий оболочки для преобразования файловых файлов из одного медиа-контейнера в другой генерирует ошибки и проблемы.

скрипт

У меня есть сценарий оболочки, предоставленный другом. Сценарий используется на компьютере с Ubuntu 10.10 для преобразования видеофайлов MKV в MP4 (MPEG-4). Рассматриваемый сценарий выглядит следующим образом (простите за отсутствие комментариев):

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

проблема

пропустить ошибки при запуске a52dec

Первая ошибка возникает только на выбранных файлах MKV, где при выполнении a52dec выполняется процесс преобразования звука.

Что происходит, так это то, что ошибка пропускается снова и снова в окне консоли / терминала. Процесс a52dec создал ожидаемое имя файла (filename.wav), но продолжает генерировать эти пропускаемые сообщения и больше не продолжает (несмотря на то, что он ушел на полчаса в одну точку, чтобы посмотреть, удастся ли решить проблему)

Если посмотреть на вывод Mediainfo для нескольких разных файлов, то кажется, что все идет не так, как этот файл включает 5.1-канальное аудио. Я, конечно, понятия не имею, как бы я преодолел эту проблему.

IsoMedia: команда не найдена

Это происходит все время, когда скрипт завершает работу, что говорит о том, что n00b не может найти нужное приложение.

Тем не менее, я не могу найти этот пакет, или если часть более крупного пакета, который он должен установить.

Еще более запутанно то, что этот файл не вызывается во время выполнения скрипта, а вызывается только после запуска команды rm для очистки.

Дополнительная информация

Пример вывода Mediainfo для файла MKV, который транскодирует без проблем

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%)

Пример вывода Mediainfo для файла MKV, который вызывает проблемы a52dec

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%)

3 ответа3

3

MKV в MP4 скрипт повторного смешивания

Это основано на сценарии Винчестера , размещенном в его ответе здесь. Я начал с его, и в конце концов он переписал большинство из них, но концепция та же.

Основная функция - взять файл MKV, содержащий видео h.264 и немного аудио, и преобразовать его в файл MP4/M4V.

Моя цель - сделать полученные файлы совместимыми с iPad и AppleTV, но он должен работать со всем, что может обрабатывать файлы MP4/M4V. Видео не транскодируется, поэтому качество остается на том же уровне, звук конвертируется при необходимости, но дорожки более высокого качества сохраняются, если это возможно.

изменения

Частичный список изменений, которые я сделал:

  • Обработка нескольких файлов или каталогов, переданных в качестве аргументов
  • Использует (и требует) более высокое качество NeroAAC для кодирования аудио AAC из AC3 или DTS
  • Обработка нескольких звуковых дорожек в соответствии со стандартом AppleTV для обеспечения надлежащего воспроизведения и объемного звучания на AppleTV:
    • 160 кБ / с стерео AAC
    • (Необязательно) AC-3 (обычно объемный звук) в качестве второй дорожки, отключен
  • Преобразование DTS в AC-3
  • Обработка нескольких дорожек независимо от порядка (например, AAC, Video, AC3)
  • Различные изменения в кодировке, облегчающие последующее изменение

Требования

Сценарий требует вышеупомянутого NeroAAC, а также Aften (кодирование AC3) и libdca/dcadec (декодирование DTS). Как и в оригинальном скрипте, ffmpeg также требуется.

Известные вопросы

Сценарий довольно пуленепробиваемый - если он сталкивается с чем-то, с чем он не может справиться, он обычно игнорируется или завершается. Исходные файлы остаются без изменений, поэтому вероятность потери данных практически отсутствует.

Я использовал его во многих моих медиатеках, и многие изменения были направлены на исправление ошибок, с которыми я столкнулся.

Тем не менее, есть несколько вещей, о которых нужно знать, и есть возможности для улучшения:

  • Обработка нескольких звуковых дорожек одного типа - 1 AC3 и 1 AAC - это хорошо, но 2 AAC дорожки не будут работать. Это не должно часто появляться, но имейте это в виду.
  • Нет поддержки не аудио / видео треков. Субтитры, главы и произведения искусства все игнорируются.
  • Нет обнаружения объемного звука AAC. Скрипт копирует любой трек AAC, он не будет микшироваться до стерео. Технически для поддержки iPad и AppleTV основная звуковая дорожка должна быть стерео AAC, но я думаю, что в большинстве случаев iPad или AppleTV могут справиться с этим изящно.

Код и использование

Я публикую это здесь, надеясь, что кто-то найдет это полезным - пожалуйста, не стесняйтесь использовать и модифицировать, как считаете нужным для некоммерческого использования. Если вы предложите интересную модификацию, было бы неплохо, если бы вы поделились ею здесь или в другом месте.

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

Инструмент FFmpeg может делать большую часть того, что описано здесь.

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

В цикле for (remux каждый * .mkv в каталоге):

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

... будет работать большую часть времени, так как большинство файлов MKV будут иметь видео h.264 и аудио AAC. Чтобы преобразовать файл, который не использует их:

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

Для получения дополнительной информации см. Руководства по кодированию x264 и AAC в википедии FFmpeg.

Если вы хотите транскодировать только те файлы, которые обязательно должны быть конвертированы, вы можете использовать скрипт bash следующим образом:

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

Привет71 вызвал мысль с его комментарием ffmpeg, и я нашел свой ответ после некоторого дополнительного поиска.

Копия успешного кода для преобразования файла выглядит следующим образом. Также происходит сбой немного более изящно, когда используется нечетный аудиоформат.

(Комментарии добавлены, чтобы было легче понять)

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .