Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 4개 있습니다.)
(시리즈 글이 7개 있습니다.)
.NET Framework: 288. FFmpeg.exe를 이용한 C# 동영상 인코더 예제
; https://www.sysnet.pe.kr/2/0/1210

개발 환경 구성: 622. vcpkg로 ffmpeg를 빌드하는 경우 생성될 구성 요소 제어하는 방법
; https://www.sysnet.pe.kr/2/0/12900

개발 환경 구성: 623. ffmpeg.exe를 사용해 비디오 파일의 이미지를 PGM(Portable Gray Map) 파일 포맷으로 출력하는 방법
; https://www.sysnet.pe.kr/2/0/12912

개발 환경 구성: 626. ffmpeg.exe를 사용해 비디오 파일을 MPEG1 포맷으로 변경하는 방법
; https://www.sysnet.pe.kr/2/0/12923

개발 환경 구성: 634. ffmpeg.exe - 기존 동영상 컨테이너에 다중 스트림을 추가하는 방법
; https://www.sysnet.pe.kr/2/0/12947

개발 환경 구성: 636. ffmpeg.exe를 이용해 planar 포맷의 데이터를 packed 형식으로 변환하는 방법?
; https://www.sysnet.pe.kr/2/0/12957

개발 환경 구성: 639. ffmpeg.exe - Intel Quick Sync Video(qsv)를 이용한 인코딩
; https://www.sysnet.pe.kr/2/0/12973




ffmpeg.exe - 기존 동영상 컨테이너에 다중 스트림을 추가하는 방법

다중 스트림 추가를 위해 예제를 구해 볼까요? ^^

우선, youtube-dl로 동영상이 지원하는 미디어 정보를 -f 옵션으로 조회할 수 있습니다.

C:\temp> youtube-dl.exe -F f-sxdm4QIvc
[youtube] f-sxdm4QIvc: Downloading webpage
[info] Available formats for f-sxdm4QIvc:
format code  extension  resolution note
249          webm       audio only tiny   53k , webm_dash container, opus @ 53k (48000Hz), 1.20MiB
250          webm       audio only tiny   70k , webm_dash container, opus @ 70k (48000Hz), 1.57MiB
140          m4a        audio only tiny  129k , m4a_dash container, mp4a.40.2@129k (44100Hz), 2.90MiB
251          webm       audio only tiny  134k , webm_dash container, opus @134k (48000Hz), 3.02MiB
278          webm       256x144    144p   85k , webm_dash container, vp9@  85k, 30fps, video only, 1.92MiB
160          mp4        256x144    144p   91k , mp4_dash container, avc1.4d400c@  91k, 30fps, video only, 2.04MiB
242          webm       426x240    240p  137k , webm_dash container, vp9@ 137k, 30fps, video only, 3.09MiB
133          mp4        426x240    240p  209k , mp4_dash container, avc1.4d4015@ 209k, 30fps, video only, 4.69MiB
243          webm       640x360    360p  214k , webm_dash container, vp9@ 214k, 30fps, video only, 4.80MiB
134          mp4        640x360    360p  442k , mp4_dash container, avc1.4d401e@ 442k, 30fps, video only, 9.92MiB
244          webm       854x480    480p  349k , webm_dash container, vp9@ 349k, 30fps, video only, 7.83MiB
135          mp4        854x480    480p  810k , mp4_dash container, avc1.4d401f@ 810k, 30fps, video only, 18.17MiB
247          webm       1280x720   720p  608k , webm_dash container, vp9@ 608k, 30fps, video only, 13.63MiB
136          mp4        1280x720   720p 1560k , mp4_dash container, avc1.64001f@1560k, 30fps, video only, 34.97MiB
248          webm       1920x1080  1080p  989k , webm_dash container, vp9@ 989k, 30fps, video only, 22.18MiB
137          mp4        1920x1080  1080p 3073k , mp4_dash container, avc1.640028@3073k, 30fps, video only, 68.86MiB
18           mp4        640x360    360p  543k , avc1.42001E, 30fps, mp4a.40.2 (44100Hz), 12.19MiB (best)

이것을 다운로드해,

C:\temp> youtube-dl.exe f-sxdm4QIvc -o test.mkv
[youtube] f-sxdm4QIvc: Downloading webpage
WARNING: Requested formats are incompatible for merge and will be merged into mkv.
[download] Destination: test.mkv.f137
[download] 100% of 68.86MiB in 15:26
[download] Destination: test.mkv.f251
[download] 100% of 3.02MiB in 00:40
[ffmpeg] Merging formats into "test2.mkv.mkv"
Deleting original file test.mkv.f137 (pass -k to keep)
Deleting original file test.mkv.f251 (pass -k to keep)

ffprobe로 조사해 보면,

c:\temp> ffprobe test.mkv
ffprobe version 4.4.1 Copyright (c) 2007-2021 the FFmpeg developers
  built with Microsoft (R) C/C++ Optimizing Compiler Version 19.30.30705 for x64
  configuration: ...[생략]...
  libpostproc    55.  9.100 / 55.  9.100
Input #0, matroska,webm, from 'test.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    ENCODER         : Lavf58.45.100
  Duration: 00:03:07.98, start: -0.007000, bitrate: 3206 kb/s
  Stream #0:0: Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc.
      DURATION        : 00:03:07.954000000
  Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      DURATION        : 00:03:07.981000000

h264 비디오와 opus 오디오 스트림이 있는 것을 확인할 수 있습니다.

테스트를 위해, 44100 Hz의 오디오 스트림을 하나 더 다운로드하고,

c:\temp> youtube-dl.exe -f 140 f-sxdm4QIvc -o test.m4a
[youtube] f-sxdm4QIvc: Downloading webpage
[download] Destination: test.m4a
[download] 100% of 2.90MiB in 00:39
[ffmpeg] Correcting container in "test.m4a"

이에 더해 640x360 해상도의 비디오 스트림도 다운로드합니다.

c:\temp> youtube-dl.exe -f 243 f-sxdm4QIvc -o test.webm
[youtube] f-sxdm4QIvc: Downloading webpage
[download] Destination: test.webm
[download] 100% of 4.80MiB in 01:04

이렇게 소스가 준비되었는데요, 그럼 어떻게 스트림을 추가할 수 있을까요? 이에 대해서는 다음의 질문/답변에 잘 정리되어 있습니다.

ffmpeg - add 3 audio streams to video
; https://stackoverflow.com/questions/70001130/ffmpeg-add-3-audio-streams-to-video

즉, -map 옵션을 사용하는 것인데요, 가령 이렇게 명령을 내리면,

ffmpeg -i video.mp4 -i input1.mp3 -i input2.mp3 
        -map 0 -map 1:a -map 2:a 
        -c:v copy -shortest 
        output.mp4

사용된 map 옵션은 다음과 같은 의미를 갖습니다.

-map 0 to copy all streams from the input #0 (video)
-map 1:a to include all audio streams from input#1 file (audio1)
-map 2:a to include all audio streams from input#2 file (audio2)

따라서, 제가 이 글에서 다운로드한 상황에서는,

test.mkv: 기준이 되는 미디어 파일, 오디오와 비디오 스트림 모두 존재
test.m4a: 추가할 스트림, 오디오만 존재
test.webm: 추가할 스트림, 비디오만 존재

이렇게 명령을 내릴 수 있습니다.

C:\temp> ffmpeg -i test.mkv -i test.m4a -i test.webm -map 0 -map 1:a -map 2:v -c:v copy -shortest output2.mp4
ffmpeg version 4.3.2-2021-02-27-full_build-www.gyan.dev Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 10.2.0 (Rev6, Built by MSYS2 project)
  configuration: ...[생략]...
  libpostproc    55.  7.100 / 55.  7.100
Input #0, matroska,webm, from 'test.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    ENCODER         : Lavf58.45.100
  Duration: 00:03:07.98, start: -0.007000, bitrate: 3206 kb/s
    Stream #0:0: Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc.
      DURATION        : 00:03:07.954000000
    Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      DURATION        : 00:03:07.981000000
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'test.m4a':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf58.45.100
  Duration: 00:03:08.01, start: 0.000000, bitrate: 129 kb/s
    Stream #1:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
      handler_name    : ISO Media file produced by Google Inc.
Input #2, matroska,webm, from 'test.webm':
  Metadata:
    encoder         : google/video-file
  Duration: 00:03:07.95, start: 0.000000, bitrate: 214 kb/s
    Stream #2:0(eng): Video: vp9 (Profile 0), yuv420p(tv, bt709), 640x360, SAR 1:1 DAR 16:9, 29.97 fps, 29.97 tbr, 1k tbn, 1k tbc (default)
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (opus (native) -> aac (native))
  Stream #1:0 -> #0:2 (aac (native) -> aac (native))
  Stream #2:0 -> #0:3 (copy)
Press [q] to stop, [?] for help
Output #0, mp4, to 'output2.mp4':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    encoder         : Lavf58.45.100
    Stream #0:0: Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 29.97 fps, 29.97 tbr, 16k tbn, 1k tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc.
      DURATION        : 00:03:07.954000000
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      DURATION        : 00:03:07.981000000
      encoder         : Lavc58.91.100 aac
    Stream #0:2(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : ISO Media file produced by Google Inc.
      encoder         : Lavc58.91.100 aac
    Stream #0:3(eng): Video: vp9 (Profile 0) (vp09 / 0x39307076), yuv420p(tv, bt709), 640x360 [SAR 1:1 DAR 16:9], q=2-31, 29.97 fps, 29.97 tbr, 16k tbn, 1k tbc (default)
frame= 5633 fps=1836 q=-1.0 Lq=-1.0 size=   81540kB time=00:03:07.93 bitrate=3554.4kbits/s speed=61.3x
video:75317kB audio:5901kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.396938%
[aac @ 000002a27b0333c0] Qavg: 207.853
[aac @ 000002a27b035380] Qavg: 227.588

실제로 다중 오디오 스트림이 되었는지 확인해 볼까요? ^^

C:\temp> ffprobe output2.mp4
ffprobe version 4.4.1 Copyright (c) 2007-2021 the FFmpeg developers
  built with Microsoft (R) C/C++ Optimizing Compiler Version 19.30.30705 for x64
  configuration: ...[생략]...
  libpostproc    55.  9.100 / 55.  9.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output2.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.45.100
  Duration: 00:03:07.95, start: 0.000000, bitrate: 3553 kb/s
  Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 3070 kb/s, 29.97 fps, 29.97 tbr, 16k tbn, 59.94 tbc (default)
    Metadata:
      handler_name    : ISO Media file produced by Google Inc.
      vendor_id       : [0][0][0][0]
  Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:2(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : ISO Media file produced by Google Inc.
      vendor_id       : [0][0][0][0]
  Stream #0:3(eng): Video: vp9 (Profile 0) (vp09 / 0x39307076), yuv420p(tv, bt709), 640x360, 212 kb/s, SAR 1:1 DAR 16:9, 29.97 fps, 29.97 tbr, 16k tbn, 16k tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]

보는 바와 같이 동영상 컨테이너에 4개의 스트림(2개의 오디오, 2개의 비디오)이 잘 들어갔습니다. 재생 테스트도 해볼까요? ^^

ffplay로 -vst와 -ast 옵션을 사용하면 각각 비디오 스트림과 오디오 스트림을 선택해서 재생할 수 있습니다. 예를 들어, 위의 상황에서 만약 640x360 비디오로 44100 Hz 오디오를 재생하고 싶다면 다음과 같이 명령을 내리면 됩니다.

// -ast: 2번 오디오 스트림
// -vst: 3번 비디오 스트림

C:\temp> ffplay output2.mp4 -ast 2 -vst 3

그래서 ffplay의 재생 화면은 640x360 크기로 나옵니다. ffplay 외에, 재미있게도 이걸 GOM Player로 재생해 보면 다음과 같이 2개의 비디오를 함께 보여줍니다.

(사진은 유튜브 영상 "디에이드"의 "안다은" 님이고 사용을 허락받고 올립니다.)
ffmpeg_add_stream_1.png

또한, 작은 비디오 화면을 클릭하면 큰 화면과 작은 화면의 렌더링이 서로 바뀝니다. 즉, 1920x1080 비디오 렌더링 중에 작은 화면을 클릭하면 640x360 비디오가 큰 화면에 나와 이미지가 다소 깨져 보입니다. 그리고 다시 작은 화면을 클릭하면 1920x1080 비디오가 큰 화면으로 렌더링됩니다. 은근히, GOM 플레이어가 작은 부분까지 꽤나 세심하게 신경 쓴 것을 확인할 수 있습니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 1/30/2022]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  3  4  [5]  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13508정성태1/3/20242141오류 유형: 886. ORA-28000: the account is locked
13507정성태1/2/20242817닷넷: 2191. C# - IPGlobalProperties를 이용해 netstat처럼 사용 중인 Socket 목록 구하는 방법파일 다운로드1
13506정성태12/29/20232388닷넷: 2190. C# - 닷넷 코어/5+에서 달라지는 System.Text.Encoding 지원
13505정성태12/27/20232935닷넷: 2189. C# - WebSocket 클라이언트를 닷넷으로 구현하는 예제 (System.Net.WebSockets)파일 다운로드1
13504정성태12/27/20232512닷넷: 2188. C# - ASP.NET Core SignalR로 구현하는 채팅 서비스 예제파일 다운로드1
13503정성태12/27/20232380Linux: 67. WSL 환경 + mlocate(locate) 도구의 /mnt 디렉터리 검색 문제
13502정성태12/26/20232478닷넷: 2187. C# - 다른 프로세스의 환경변수 읽는 예제파일 다운로드1
13501정성태12/25/20232293개발 환경 구성: 700. WSL + uwsgi - IPv6로 바인딩하는 방법
13500정성태12/24/20232345디버깅 기술: 194. Windbg - x64 가상 주소를 물리 주소로 변환
13498정성태12/23/20233029닷넷: 2186. 한국투자증권 KIS Developers OpenAPI의 C# 래퍼 버전 - eFriendOpenAPI NuGet 패키지
13497정성태12/22/20232448오류 유형: 885. Visual Studiio - error : Could not connect to the remote system. Please verify your connection settings, and that your machine is on the network and reachable.
13496정성태12/21/20232431Linux: 66. 리눅스 - 실행 중인 프로세스 내부의 환경변수 설정을 구하는 방법 (gdb)
13495정성태12/20/20232399Linux: 65. clang++로 공유 라이브러리의 -static 옵션 빌드가 가능할까요?
13494정성태12/20/20232530Linux: 64. Linux 응용 프로그램의 (C++) so 의존성 줄이기(ReleaseMinDependency) - 두 번째 이야기
13493정성태12/19/20232623닷넷: 2185. C# - object를 QueryString으로 직렬화하는 방법
13492정성태12/19/20232311개발 환경 구성: 699. WSL에 nopCommerce 예제 구성
13491정성태12/19/20232258Linux: 63. 리눅스 - 다중 그룹 또는 사용자를 리소스에 권한 부여
13490정성태12/19/20232383개발 환경 구성: 698. Golang - GLIBC 의존을 없애는 정적 빌드 방법
13489정성태12/19/20232165개발 환경 구성: 697. GoLand에서 ldflags 지정 방법
13488정성태12/18/20232094오류 유형: 884. HTTP 500.0 - 명령행에서 실행한 ASP.NET Core 응용 프로그램을 실행하는 방법
13487정성태12/16/20232400개발 환경 구성: 696. C# - 리눅스용 AOT 빌드를 docker에서 수행 [1]
13486정성태12/15/20232214개발 환경 구성: 695. Nuget config 파일에 값 설정/삭제 방법
13485정성태12/15/20232095오류 유형: 883. dotnet build/restore - error : Root element is missing
13484정성태12/14/20232171개발 환경 구성: 694. Windows 디렉터리 경로를 WSL의 /mnt 포맷으로 구하는 방법
13483정성태12/14/20232312닷넷: 2184. C# - 하나의 resource 파일을 여러 프로그램에서 (AOT 시에도) 사용하는 방법파일 다운로드1
13482정성태12/13/20232898닷넷: 2183. C# - eFriend Expert OCX 예제를 .NET Core/5+ Console App에서 사용하는 방법 [2]파일 다운로드1
1  2  3  4  [5]  6  7  8  9  10  11  12  13  14  15  ...