[태그:] handbrake

  • HandBrakeCLI – 폴더 내의 동영상 일괄 변환하기

    handbrakecli를 이용해서 폴더 내의 동영상을 미리 정의된 preset을 사용해서 일괄 변환하는 shell script이다. 여러 동영상 파일들을 한번에 h265 hevc 형식으로 일괄 변환하고 싶을 때 퍽 유용하다.

    #!/bin/bash
    #
    # This script requires HandBrakeCLI. On macOS, at least, you need to download
    # and install it separately from Handbrake.
    #
    # See: https://handbrake.fr/downloads2.php
    
    if [ -z "$1" ] ; then
        TRANSCODEDIR="."
    else
        TRANSCODEDIR="$1"
    fi
        # Change the preset if you like (see options: "HandBrakeCLI --preset-list")
        # If you want to transcode ALL movie files, remove the -name option.
        find "$TRANSCODEDIR"/* -type f -name "*.mp4" -exec bash -c 'HandBrakeCLI -i "$1" -o "${1%\.*}".hevc.mp4 --preset-import-file ~/2hevc.json -Z "2hevc"' __ {} \;

    https://www.jeffgeerling.com/blog/2022/batch-transcode-folder-videos-handbrakes-cli

  • HandBrake – vtb_h265 인코더를 이용한 동영상 인코딩

    여러가지 이유로 소장용 영화나 TV프로그램들을 변환해야하는 상황이 있을 수 있다. 요사이 Plex Media Server(PMS)에서 녹화한 TV프로그램들의 파일 크기가 너무 커서 SSD에 담아두기 부담스러운 상황이 발생했다.

    녹화한 TV 파일들이 HD 방송표준 형식인 mpeg2ts 형식의 동영상들이라서 공간을 제법 차지하고 있어서 h.265 hevc로 파일 크기를 줄이고 싶있었다.

    변환에 사용할 소프트웨어로는 상용 프로그램인 Final Cut Pro – Compressor를 선택 할 수 있고 무료로 사용할 수 있는 HandBrake를 선택할 수 있는데 나는 가난하므로 HandBrake를 선택했다.

    HandBrake(이하 HB)는 대중적인 오픈소스 프로그램으로 내부적으로는 FFmpeg를 사용한다. 하지만 ffmpeg가 그러하듯 제공되는 너무나 다양한 옵션으로 처음 접하는 사용자들은 눈이 휘둥그레질 수 있다.

    HandBrake

    나는 Apple M1 맥북 에어를 사용 중인데 인코딩할 때 gpu 하드웨어 가속을 쓰려면 어떻게 해야 하는지가 궁금했고 원본과 비슷한 화질을 유지하면서 결과물의 파일 크기를 줄이기 위해 앞서 말한대로 hevc 코덱을 사용하기를 원했다.
    요구되는 사항들은 다음과 같이 세 가지이다.

    1. hevc 코덱과 GPU 하드웨어 가속(Hardware Acceleration)을 사용해서 인코딩하기
    2. 내게 맞는 최적의 변환 옵션 찾기 – 스윗스팟(sweet spot)을 찾아라!
    3. HandBrakeCLI를 이용해서 폴더 단위로 동영상을 손쉽게 변환 할 수 있도록 배치 스크립트 작성하기

    먼저, 내가 사용 중인 M1 맥북의 경우 하드웨어 가속을 사용하려면 HB에서는 Apple에서 제공하는 VideoToolBox(VTB) Framework을 이용하므로 HB에서 제공하는 옵션을 확인하자. 제공하는 문서는 아래의 링크에서 자세히 볼 수 있다.

    https://handbrake.fr/docs/en/latest/technical/video-videotoolbox.html

    HB에서 제공하는 VTB용 비디오 인코더는 세 가지이며

    • H.264 (VideoToolbox) – vtb_h264
    • H.265 (VideoToolbox) – vtb_h265
    • H.265 10bit (VideoToolbox) – vt_h265_10bit

    사전에 미리 제공되는 기본 프리셋은 두 가지이다.(Preset> Hardware)

    • H.265 Apple VideoToolbox 2160P 4K
    • H.265 Apple VideoToolbox 1080P

    물론 미리 제공되는 프리셋으로 변환할 수도 있지만 자신이 원하는 스윗스팟을 찾으려면 옵션들을 변경하면서 다양한 결과물을 직접 확인해야한다. 그러기위해서는 샘플영상을 만들자. (한 시간이 넘어가는 영화파일로 스윗스팟을 찾으려면 날샌다.)

    mp4 파일의 경우, 샘플영상의 자르기는 ffmpeg를 사용하며 아래 링크에서 자세한 내용들을 볼 수 있다.

    https://www.arj.no/2018/05/18/trimvideo

    ffmpeg를 설치하고 커멘드 창을 열고 아래와 같이 커멘드를 입력해 원하는 샘플 파일을 준비한다.

    ffmpeg -i input-file.mp4 -ss 00:02:30 -t 00:03:00 -c copy output-file.mp4
    ffmpeg -sseof -00:10:00 -i input.mp4 -c copy output6.mp4
    • ffmpeg
    • -i input-file.mp4 – 입력으로 사용할 파일명
    • -ss 00:02:30 – 시작 시점 (HH:MM:SS)
    • -t 00:03:00 – 기간 (3분)
    • -c copy – 재인코딩 없이 오디오와 비디오 스트림을 복사
    • output-file.mp4 – 출력으로 사용될 파일명
    • -sseof – eof(End of File)

    mkv 파일의 경우, MKVToolNix를 설치하고 아래와 같이 입력한다.

    mkvmerge -o output-file.mkv input-file.mkv --split parts:00:02:30-00:05:30
    • mkvmerge
    • -o output-file.mkv – 출력으로 사용할 파일명
    • input-file.mkv – 입력되는 파일명
    • –split parts: – 자르기를 원하는 장면의 시작되는 시점과 종료되는 시점의 타임스탬프

    두 번째로는 샘플영상이 마련되었으니 최적의 변환 옵션을 찾아야하는데 하드웨어 가속이 가능한 vtb_265 인코더의 경우에는 Constant Quality(이하 cq) 값이 중요하다.

    기본 제공되는 프리셋의 경우 FHD는 60, 4K는 55로 설정되어 있다.

    HB에서 샘플파일을 열고 Preset메뉴에서 ‘Hardware’ 폴더 내에 있는 ‘H.265 Apple VideoToolbox 1080P’ 프리셋을 선택해서 로드해 cq값을 변경해가며 시험해보자.

    왼쪽부터 원본, cq60, cq55 순이다. (원본을 확인하려면 클릭)

    나의 경우 FHD의 경우 cq 52~55가 가장 좋았다. 원하는 cq값으로 변경한 뒤 ‘Save as New Preset’을 선택해 따로 프리셋을 저장한다.

    만일 인코딩 작업 중에 M1 맥북에어가 너무 높은 온도로 인해 스로틀링이 발생하는 것을 방지하려면 HB의 ‘Video> Additional Options’에 “threads=2″를 입력하는 것과 같이 작업에 사용될 threads를 제한해 두자.

    https://www.jeffgeerling.com/blog/2022/limiting-handbrake-threads-prevent-throttling-on-m2-macbook-air

    마지막으로 원하는 cq값을 찾아서 프리셋을 완성했으므로 HandBrakeCLI를 사용해 배치작업을 실행해 보자.

    HandBrakeCLI

    HB에서는 gui 프로그램과 cli 프로그램이 서로 프리셋 공유가 되지 않는다.
    따라서 gui 앱에서 완성한 프리셋을 json파일로 내보내기를 한뒤, 다시 cli에서 그 파일을 가져오기해서 사용해야 한다.

    gui 프로그램에서 ‘Preset> Export’ 메뉴를 선택해 원하는 위치에 json 파일을 저장하고 아래와 같이 cli에서 사용하면 된다.

    HandBrakeCLI -v --preset-import-file 'exported-preset-file.json' -Z 'preset-name' -i input-file.mp4 -o output-file.mp4

    여기서 ‘preset-name‘은 ‘exported-preset-file.json‘ 내에 기입된 preset의 이름이다. (json파일을 열어보면 확인할 수 있다.)

    사용자 preset은 HandBrakeCLI에서는 별도로 저장되지 않기 때문에 변환할 때마다 써넣어줘야 한다.

    성공적으로 변환을 마쳤다면 이제 스크립트를 작성해 배치작업을 해보자.

    #!/bin/bash
    
    if [ -z "$1" ] ; then
        TRANSCODEDIR="."
    else
        TRANSCODEDIR="$1"
    fi
        find "$TRANSCODEDIR"/* -type f -name "*.mp4" -exec bash -c 'HandBrakeCLI -i "$1" -o "${1%\.*}"-out.mp4 --preset-import-file exported-preset-file.json -Z "preset-name"' __ {} \;

    https://www.jeffgeerling.com/blog/2022/batch-transcode-folder-videos-handbrakes-cli

    $>sh encoding.sh 'path-and-folder-name'

    자, 이제 원하는 TV 시리즈를 배치 작업으로 간단하게 변환할 수 있다.
    변환 작업에 사용될 thread를 제한해 두었으므로(threads=2) 맥북에서 동시에 다른 작업을 하기에도 유용하다.

    HandBrakeCLI에서 인코딩할 때 사용된 preset – AV.json

    {
      "PresetList" : [
        {
          "AlignAVStart" : false,
          "AudioCopyMask" : [
            "copy:aac"
          ],
          "AudioEncoderFallback" : "none",
          "AudioLanguageList" : [
            "any"
          ],
          "AudioList" : [
            {
              "AudioBitrate" : 160,
              "AudioCompressionLevel" : -1,
              "AudioDitherMethod" : "auto",
              "AudioEncoder" : "copy:aac",
              "AudioMixdown" : "stereo",
              "AudioNormalizeMixLevel" : false,
              "AudioSamplerate" : "auto",
              "AudioTrackDRCSlider" : 0,
              "AudioTrackGainSlider" : 0,
              "AudioTrackQuality" : -1,
              "AudioTrackQualityEnable" : false
            }
          ],
          "AudioSecondaryEncoderMode" : true,
          "AudioTrackSelectionBehavior" : "first",
          "ChapterMarkers" : true,
          "ChildrenArray" : [
    
          ],
          "Default" : false,
          "FileFormat" : "av_mp4",
          "Folder" : false,
          "FolderOpen" : false,
          "InlineParameterSets" : false,
          "MetadataPassthrough" : true,
          "Mp4iPodCompatible" : false,
          "Optimize" : false,
          "PictureAllowUpscaling" : false,
          "PictureAutoCrop" : true,
          "PictureBottomCrop" : 0,
          "PictureChromaSmoothCustom" : "",
          "PictureChromaSmoothPreset" : "off",
          "PictureChromaSmoothTune" : "none",
          "PictureColorspaceCustom" : "",
          "PictureColorspacePreset" : "off",
          "PictureCombDetectCustom" : "",
          "PictureCombDetectPreset" : "off",
          "PictureCropMode" : 2,
          "PictureDARWidth" : 1920,
          "PictureDeblockCustom" : "strength=strong:thresh=20:blocksize=8",
          "PictureDeblockPreset" : "off",
          "PictureDeblockTune" : "medium",
          "PictureDeinterlaceCustom" : "",
          "PictureDeinterlaceFilter" : "off",
          "PictureDeinterlacePreset" : "default",
          "PictureDenoiseCustom" : "",
          "PictureDenoiseFilter" : "off",
          "PictureDenoisePreset" : "light",
          "PictureDenoiseTune" : "none",
          "PictureDetelecine" : "off",
          "PictureDetelecineCustom" : "",
          "PictureForceHeight" : 0,
          "PictureForceWidth" : 0,
          "PictureHeight" : 0,
          "PictureItuPAR" : false,
          "PictureKeepRatio" : true,
          "PictureLeftCrop" : 0,
          "PictureModulus" : 2,
          "PicturePadBottom" : 0,
          "PicturePadColor" : "black",
          "PicturePadLeft" : 0,
          "PicturePadMode" : "none",
          "PicturePadRight" : 0,
          "PicturePadTop" : 0,
          "PicturePAR" : "off",
          "PicturePARHeight" : 1,
          "PicturePARWidth" : 1,
          "PictureRightCrop" : 0,
          "PictureRotate" : "angle=0:hflip=0",
          "PictureSharpenCustom" : "",
          "PictureSharpenFilter" : "off",
          "PictureSharpenPreset" : "medium",
          "PictureSharpenTune" : "none",
          "PictureTopCrop" : 0,
          "PictureUseMaximumSize" : true,
          "PictureWidth" : 0,
          "PresetDescription" : "",
          "PresetDisabled" : false,
          "PresetName" : "AV",
          "SubtitleAddCC" : false,
          "SubtitleAddForeignAudioSearch" : false,
          "SubtitleAddForeignAudioSubtitle" : false,
          "SubtitleBurnBDSub" : true,
          "SubtitleBurnBehavior" : "none",
          "SubtitleBurnDVDSub" : true,
          "SubtitleLanguageList" : [
            "any"
          ],
          "SubtitleTrackSelectionBehavior" : "none",
          "Type" : 1,
          "UsesPictureFilters" : true,
          "VideoAvgBitrate" : 175000,
          "VideoColorMatrixCodeOverride" : 0,
          "VideoEncoder" : "vt_h265",
          "VideoFramerate" : "auto",
          "VideoFramerateMode" : "vfr",
          "VideoGrayScale" : false,
          "VideoHWDecode" : 0,
          "VideoLevel" : "auto",
          "VideoMultiPass" : false,
          "VideoOptionExtra" : "threads=2",
          "VideoPreset" : "quality",
          "VideoProfile" : "auto",
          "VideoQSVDecode" : false,
          "VideoQualitySlider" : 55,
          "VideoQualityType" : 2,
          "VideoScaler" : "swscale",
          "VideoTune" : "",
          "VideoTurboMultiPass" : true,
          "x264Option" : "",
          "x264UseAdvancedOptions" : false
        }
      ],
      "VersionMajor" : 53,
      "VersionMicro" : 0,
      "VersionMinor" : 0
    }