Yuebing 리뷰 #3

Yoebing의 미디어 등록과 소비 과정을 살펴봅니다.

2023-06-11

Source

Yuebing은 source라는 object storage 설정을 여러개 가질 수 있습니다. .env의 object storage 설정은 사용자 정보, 메타데이터 정보 등을 저장하는 설정 입니다.

admin 계정으로 로그인하면 컨텐트를 저장하는 원본 파일 저쟝용 object storage를 추가할 수 있습니다. Yuebing은 원본 미디어 파일을 직접 업로드하는 기능을 제공하지는 않고 원본 파일 저장용 object storage에서 읽어와 처리합니다.

Scan

Source를 추가하면 scan 동작을 할 수 있습니다. Scan은 source object storage에 있는 파일을 읽어와 Yuebing에서 제공하는 컨텐츠 형식으로 변환하는 작업을 합니다. Yuebing의 핵심 기능이라고 할 수 있겠습니다.

Scan 과정은 앞서말한 transform이라고 하는 미디어 변환과정을 포함합니다. Transform은 먼저 source object storage에 있는 원본 파일을 Yuebing 인스턴스가 동작하는 환경의 폴더(/tmp/yuebing_workdir)로 복사하는 것으로 시작합니다. 이렇게 복사한 파일을 대상으로 mediainfo, ffmpeg 명령을 사용하여 정보 추출, thumbnail 추출, 미디어 변환등을 수행합니다.

미디어 변환과정은 대략 다음과 같습니다.

artifact_mediainfo_details_starting_xform_video

./scripts/mediainfo_wrapper '--Details=1' '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4'

mediainfo --details=1 명령을 사용하여 미디어의 메타데이터, 코덱 정보등을 얻어옵니다.

MediaInfo

artifact_mediainfo_json_starting_xform_video

./scripts/mediainfo_wrapper '--Output=JSON' --Full '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4'

mediainfo --output=json 명령으로 json 형식으로 출력합니다.

artifact_dash_mp4_starting_xform_video

./scripts/ffmpeg_wrapper -i '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4' -map '0:a' '-c:a:0' aac '-b:a:0' 48k '-ar:0' 44100 '-ac:0' 1 -map '-0:s?' -map '0:v' '-c:v:0' libx264 '-b:v:0' 192k '-s:v:0' 640x360 '-profile:v:0' main -window_size 1000000 -use_timeline 1 -use_template 1 -adaptation_sets 'id=0,streams=v id=1,streams=a' -init_seg_name 'asset_dash_mp4@video@init-streamRepresentationIDRepresentationID.extext' -media_seg_name 'asset_dash_mp4@video@chunk-streamRepresentationIDRepresentationID-NumberNumber%05d.extext' -hls_playlist true -hls_master_name 'asset_hls_m3u8@video@master.m3u8' -f dash -y '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_dash_mp4@video@001.mpd'

MPEG-DASH란 무엇입니까? | HLS와 DASH의 비교 | Cloudflare

ffmpeg 명령으로 mpeg-dash streaming 변환을 합니다.

Map audio track

-map '0:a' '-c:a:0' aac '-b:a:0' 48k '-ar:0' 44100 '-ac:0' 1 

Skip subtitle track

-map '-0:s?'

Map video track

-map '0:v' '-c:v:0' libx264 '-b:v:0' 192k '-s:v:0' 640x360 '-profile:v:0' main

the playlist should always contain all segments

-window_size 1000000

artifact_thumbnail_small_starting_xform_video

./scripts/ffmpeg_wrapper -i '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4' -s vga -vf 'fps=1/60' -y '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_small@video@%03d.jpg'

ffmpeg으로 1분 간격으로 vga(640x480) thumbnail을 생성합니다.

thumbnails

artifact_first_thumbnail_small_starting_xform_video

./scripts/ffmpeg_wrapper -ss 6 -accurate_seek -i '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4' -s vga '-frames:v' 1 -y '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_first_thumbnail_small@video@.jpg'

첫번째 프레임을 vga(640x480) thumbnail로 생성합니다.

firstThumbnail

artifact_thumbnail_medium_starting_xform_video

./scripts/ffmpeg_wrapper -i '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4' -s hd720 -vf 'fps=1/60' -y '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_medium@video@%03d.jpg'

ffmpeg으로 1분 간격으로 hd720(1280x720) thumbnail을 생성합니다.

artifact_thumbnail_large_starting_xform_video

./scripts/ffmpeg_wrapper -i '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4' -s hd1080 -vf 'fps=1/60' -y '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_large@video@%03d.jpg'

ffmpeg으로 1분 간격으로 hd1080(1920, 1080) thumbnail을 생성합니다.

artifact_first_thumbnail_large_starting_xform_video

./scripts/ffmpeg_wrapper -ss 6 -accurate_seek -i '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/source.mp4' -s hd1080 '-frames:v' 1 -y '/tmp/yuebing_workdir/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_first_thumbnail_large@video@.jpg'

첫번째 프레임을 hd1080(1920x1080) thumbnail로 생성합니다.

자막 복사

  • artifact_vttTracks_copy_starting_xform_video
  • artifact_srtTracks_copy_starting_xform_video
  • artifact_srt2vttTracks_starting_xform_video

Indexing

Indexing 과정을 통해 transform 과정을 통해 생성한 파일들의 정보를 다음과 같은 형식으로 정리합니다.

{
  "ctime": 1686467653174,
  "assets": {
    "dash_mp4": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_dash_mp4@video@001.mpd"
    ],
    "first_thumbnail_large": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_first_thumbnail_large@video@.jpg"
    ],
    "first_thumbnail_medium": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_first_thumbnail_medium@video@.jpg"
    ],
    "first_thumbnail_small": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_first_thumbnail_small@video@.jpg"
    ],
    "hls_m3u8": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_hls_m3u8@video@master.m3u8"
    ],
    "mediainfo_details": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_mediainfo_details@video@.txt"
    ],
    "mediainfo_json": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_mediainfo_json@video@.json"
    ],
    "thumbnail_large": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_large@video@001.jpg",
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_large@video@002.jpg"
    ],
    "thumbnail_medium": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_medium@video@001.jpg",
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_medium@video@002.jpg"
    ],
    "thumbnail_small": [
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_small@video@001.jpg",
      "assets/8b/5c/34/8b5c34fb9d00015880cb408f9d6410ace182b529/asset_thumbnail_small@video@002.jpg"
    ]
  },
  "status": {
    "info": true,
    "ready": true
  }
}

마치며

Yuebing은 개인 미디어 파일들을 손쉽게 관리하고 공유할 수 있도록 도와줍니다. 파일기반으로 회원을 관리하는 방식과 함께, 비디오 변환, 인덱싱, 검색등에 대한 다양한 인사이트를 얻을 수 있었습니다.

Loading script...