성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - ffmpeg(FFmpeg.AutoGen) AVFormatContext를 이용해 ffprobe처럼 정보 출력</h1> <p> ffmpeg에서 하나의 동영상 정보를 취급하는 단위가 AVFormatContext입니다. 이것을 얻으려면 우선 avformat_open_input을 호출하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > string filePath = @"D:\media_sample\output2.mp4"; <span style='color: blue; font-weight: bold'>AVFormatContext* av_context = null;</span> int ret = ffmpeg.<span style='color: blue; font-weight: bold'>avformat_open_input</span>(&av_context, filePath, null, null); </pre> <br /> avformat_open_input에 av_context 변수를 null로 넣으면 할당해서 반환합니다. 혹은, 미리 avformat_alloc_context 함수를 이용해 할당해도 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>AVFormatContext* av_context = ffmpeg.avformat_alloc_context();</span> int ret = ffmpeg.avformat_open_input(&av_context, filePath, null, null); </pre> <br /> 일단, 이렇게 열고나면 AVFormatContext에 있는 몇몇 정보를 조회할 수 있습니다. 지난 글에서 메타데이터를 조회하는 예제를 올렸는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - ffmpeg(FFmpeg.AutoGen)를 이용해 멀티미디어 파일의 메타데이터를 보여주는 예제(metadata.c) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12936'>https://www.sysnet.pe.kr/2/0/12936</a> </pre> <br /> 그 코드에서는 avformat_open_input + avformat_find_stream_info 함수를 호출했었죠? 위의 테스트를 해보니 굳이 avformat_find_stream_info 함수는 호출하지 않아도 조회가 되었습니다. (어쨌든, 이렇게라도 정리를 해서 접근하니 뭔가 손에 잡히는 것 같은 기분입니다. ^^)<br /> <br /> 참고로, 이렇게 AVFormatContext 정보를 avformat_open_input으로 얻어도 해당 구조체의 모든 내용이 채워지는 것은 아닙니다. 가령, bitrate 등의 정보는 avformat_find_stream_info 함수를 추가 호출해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ffmpeg.avformat_find_stream_info(av_context, null); </pre> <br /> 마지막으로 AVFormatContext의 사용을 마쳤으면 avformat_close_input을 이용해 자원을 해제할 수 있습니다. 그리고 이를 종합하면 다음과 같은 식으로 예제 코드를 정리할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > string filePath = @"D:\media_sample\output2.mp4"; int ret = ffmpeg.avformat_open_input(&av_context, filePath, null, null); if (ret != 0) { return; } // ...[avformat_open_input으로 얻을 수 있는 정보 조회]... ffmpeg.avformat_find_stream_info(av_context, null); // ...[avformat_find_stream_info로 얻을 수 있는 정보 조회]... ffmpeg.avformat_close_input(&av_context); </pre> <br /> 그나저나, AVFormatContext에는 정말 많은 정보들이 있는데요,<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // // Summary: // Format I/O context. New fields can be added to the end with minor version bumps. // Removal, reordering and changes to existing fields require a major version bump. // sizeof(AVFormatContext) must not be used outside libav*, use avformat_alloc_context() // to create an AVFormatContext. public struct AVFormatContext { // // Summary: // A class for logging and avoptions. Set by avformat_alloc_context(). Exports (de)muxer // private options if they exist. public unsafe AVClass* av_class; // // Summary: // The input container format. public unsafe AVInputFormat* iformat; // // Summary: // The output container format. public unsafe AVOutputFormat* oformat; // // Summary: // Format private data. This is an AVOptions-enabled struct if and only if iformat/oformat.priv_class // is not NULL. public unsafe void* priv_data; // // Summary: // I/O context. public unsafe AVIOContext* pb; // // Summary: // Flags signalling stream properties. A combination of AVFMTCTX_*. Set by libavformat. public int ctx_flags; // // Summary: // Number of elements in AVFormatContext.streams. public uint nb_streams; // // Summary: // A list of all streams in the file. New streams are created with avformat_new_stream(). public unsafe AVStream** streams; // // Summary: // input or output filename [Obsolete("Use url instead.")] public byte_array1024 filename; // // Summary: // input or output URL. Unlike the old filename field, this field has no length // restriction. public unsafe byte* url; // // Summary: // Position of the first frame of the component, in AV_TIME_BASE fractional seconds. // NEVER set this value directly: It is deduced from the AVStream values. public long start_time; // // Summary: // Duration of the stream, in AV_TIME_BASE fractional seconds. Only set this value // if you know none of the individual stream durations and also do not set any of // them. This is deduced from the AVStream values if not set. public long duration; // // Summary: // Total stream bitrate in bit/s, 0 if not available. Never set it directly if the // file_size and the duration are known as FFmpeg can compute it automatically. public long bit_rate; public uint packet_size; public int max_delay; // // Summary: // Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*. Set by // the user before avformat_open_input() / avformat_write_header(). public int flags; // // Summary: // Maximum size of the data read from input for determining the input container // format. Demuxing only, set by the caller before avformat_open_input(). public long probesize; // // Summary: // Maximum duration (in AV_TIME_BASE units) of the data read from input in avformat_find_stream_info(). // Demuxing only, set by the caller before avformat_find_stream_info(). Can be set // to 0 to let avformat choose using a heuristic. public long max_analyze_duration; public unsafe byte* key; public int keylen; public uint nb_programs; public unsafe AVProgram** programs; // // Summary: // Forced video codec_id. Demuxing: Set by user. public AVCodecID video_codec_id; // // Summary: // Forced audio codec_id. Demuxing: Set by user. public AVCodecID audio_codec_id; // // Summary: // Forced subtitle codec_id. Demuxing: Set by user. public AVCodecID subtitle_codec_id; // // Summary: // Maximum amount of memory in bytes to use for the index of each stream. If the // index exceeds this size, entries will be discarded as needed to maintain a smaller // size. This can lead to slower or less accurate seeking (depends on demuxer). // Demuxers for which a full in-memory index is mandatory will ignore this. - muxing: // unused - demuxing: set by user public uint max_index_size; // // Summary: // Maximum amount of memory in bytes to use for buffering frames obtained from realtime // capture devices. public uint max_picture_buffer; // // Summary: // Number of chapters in AVChapter array. When muxing, chapters are normally written // in the file header, so nb_chapters should normally be initialized before write_header // is called. Some muxers (e.g. mov and mkv) can also write chapters in the trailer. // To write chapters in the trailer, nb_chapters must be zero when write_header // is called and non-zero when write_trailer is called. - muxing: set by user - // demuxing: set by libavformat public uint nb_chapters; public unsafe AVChapter** chapters; // // Summary: // Metadata that applies to the whole file. public unsafe AVDictionary* metadata; // // Summary: // Start time of the stream in real world time, in microseconds since the Unix epoch // (00:00 1st January 1970). That is, pts=0 in the stream was captured at this real // world time. - muxing: Set by the caller before avformat_write_header(). If set // to either 0 or AV_NOPTS_VALUE, then the current wall-time will be used. - demuxing: // Set by libavformat. AV_NOPTS_VALUE if unknown. Note that the value may become // known after some number of frames have been received. public long start_time_realtime; // // Summary: // The number of frames used for determining the framerate in avformat_find_stream_info(). // Demuxing only, set by the caller before avformat_find_stream_info(). public int fps_probe_size; // // Summary: // Error recognition; higher values will detect more errors but may misdetect some // more or less valid parts as errors. Demuxing only, set by the caller before avformat_open_input(). public int error_recognition; // // Summary: // Custom interrupt callbacks for the I/O layer. public AVIOInterruptCB interrupt_callback; // // Summary: // Flags to enable debugging. public int debug; // // Summary: // Maximum buffering duration for interleaving. public long max_interleave_delta; // // Summary: // Allow non-standard and experimental extension public int strict_std_compliance; // // Summary: // Flags indicating events happening on the file, a combination of AVFMT_EVENT_FLAG_*. public int event_flags; // // Summary: // Maximum number of packets to read while waiting for the first timestamp. Decoding // only. public int max_ts_probe; // // Summary: // Avoid negative timestamps during muxing. Any value of the AVFMT_AVOID_NEG_TS_* // constants. Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts // is in use) - muxing: Set by user - demuxing: unused public int avoid_negative_ts; // // Summary: // Transport stream id. This will be moved into demuxer private options. Thus no // API/ABI compatibility public int ts_id; // // Summary: // Audio preload in microseconds. Note, not all formats support this and unpredictable // things may happen if it is used when not supported. - encoding: Set by user - // decoding: unused public int audio_preload; // // Summary: // Max chunk time in microseconds. Note, not all formats support this and unpredictable // things may happen if it is used when not supported. - encoding: Set by user - // decoding: unused public int max_chunk_duration; // // Summary: // Max chunk size in bytes Note, not all formats support this and unpredictable // things may happen if it is used when not supported. - encoding: Set by user - // decoding: unused public int max_chunk_size; // // Summary: // forces the use of wallclock timestamps as pts/dts of packets This has undefined // results in the presence of B frames. - encoding: unused - decoding: Set by user public int use_wallclock_as_timestamps; // // Summary: // avio flags, used to force AVIO_FLAG_DIRECT. - encoding: unused - decoding: Set // by user public int avio_flags; // // Summary: // The duration field can be estimated through various ways, and this field can // be used to know how the duration was estimated. - encoding: unused - decoding: // Read by user public AVDurationEstimationMethod duration_estimation_method; // // Summary: // Skip initial bytes when opening stream - encoding: unused - decoding: Set by // user public long skip_initial_bytes; // // Summary: // Correct single timestamp overflows - encoding: unused - decoding: Set by user public uint correct_ts_overflow; // // Summary: // Force seeking to any (also non key) frames. - encoding: unused - decoding: Set // by user public int seek2any; // // Summary: // Flush the I/O context after each packet. - encoding: Set by user - decoding: // unused public int flush_packets; // // Summary: // format probing score. The maximal score is AVPROBE_SCORE_MAX, its set when the // demuxer probes the format. - encoding: unused - decoding: set by avformat, read // by user public int probe_score; // // Summary: // number of bytes to read maximally to identify format. - encoding: unused - decoding: // set by user public int format_probesize; // // Summary: // ',' separated list of allowed decoders. If NULL then all are allowed - encoding: // unused - decoding: set by user public unsafe byte* codec_whitelist; // // Summary: // ',' separated list of allowed demuxers. If NULL then all are allowed - encoding: // unused - decoding: set by user public unsafe byte* format_whitelist; // // Summary: // An opaque field for libavformat internal usage. Must not be accessed in any way // by callers. public unsafe AVFormatInternal* @internal; // // Summary: // IO repositioned flag. This is set by avformat when the underlaying IO context // read pointer is repositioned, for example when doing byte based seeking. Demuxers // can use the flag to detect such changes. public int io_repositioned; // // Summary: // Forced video codec. This allows forcing a specific decoder, even when there are // multiple with the same codec_id. Demuxing: Set by user public unsafe AVCodec* video_codec; // // Summary: // Forced audio codec. This allows forcing a specific decoder, even when there are // multiple with the same codec_id. Demuxing: Set by user public unsafe AVCodec* audio_codec; // // Summary: // Forced subtitle codec. This allows forcing a specific decoder, even when there // are multiple with the same codec_id. Demuxing: Set by user public unsafe AVCodec* subtitle_codec; // // Summary: // Forced data codec. This allows forcing a specific decoder, even when there are // multiple with the same codec_id. Demuxing: Set by user public unsafe AVCodec* data_codec; // // Summary: // Number of bytes to be written as padding in a metadata header. Demuxing: Unused. // Muxing: Set by user via av_format_set_metadata_header_padding. public int metadata_header_padding; // // Summary: // User data. This is a place for some private data of the user. public unsafe void* opaque; // // Summary: // Callback used by devices to communicate with application. public AVFormatContext_control_message_cb_func control_message_cb; // // Summary: // Output timestamp offset, in microseconds. Muxing: set by user public long output_ts_offset; // // Summary: // dump format separator. can be ", " or " " or anything else - muxing: Set by user. // - demuxing: Set by user. public unsafe byte* dump_separator; // // Summary: // Forced Data codec_id. Demuxing: Set by user. public AVCodecID data_codec_id; // // Summary: // Called to open further IO contexts when needed for demuxing. [Obsolete("Use io_open and io_close.")] public AVFormatContext_open_cb_func open_cb; // // Summary: // ',' separated list of allowed protocols. - encoding: unused - decoding: set by // user public unsafe byte* protocol_whitelist; // // Summary: // A callback for opening new IO streams. public AVFormatContext_io_open_func io_open; // // Summary: // A callback for closing the streams opened with AVFormatContext.io_open(). public AVFormatContext_io_close_func io_close; // // Summary: // ',' separated list of disallowed protocols. - encoding: unused - decoding: set // by user public unsafe byte* protocol_blacklist; // // Summary: // The maximum number of streams. - encoding: unused - decoding: set by user public int max_streams; // // Summary: // Skip duration calcuation in estimate_timings_from_pts. - encoding: unused - decoding: // set by user public int skip_estimate_duration_from_pts; // // Summary: // Maximum number of packets that can be probed - encoding: unused - decoding: set // by user public int max_probe_packets; } } </pre> <br /> 저도 아직 초보라 많은 것들을 알 수 없고, 겨우 다음과 같은 식으로 조회를 해봤습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > AVFormatContext* av_context = ffmpeg.avformat_alloc_context(); // null; string filePath = @"D:\media_sample\output2.mp4"; int ret = ffmpeg.avformat_open_input(&av_context, filePath, null, null); if (ret != 0) { return; } Console.WriteLine("[metadata]"); WriteMetadata(av_context->metadata); Console.WriteLine(); Console.WriteLine("[context-info]"); Console.WriteLine($"duration: {(decimal)av_context->duration / ffmpeg.AV_TIME_BASE}"); Console.WriteLine($"# of streams: {av_context->nb_streams}"); Console.WriteLine($"url: {Marshal.PtrToStringAnsi(new IntPtr(av_context->url))}"); ffmpeg.avformat_find_stream_info(av_context, null); Console.WriteLine($"start time: {av_context->start_time}"); Console.WriteLine($"bitrate: {(decimal)av_context->bit_rate / 1000} kb/s"); for (int i = 0; i < av_context->nb_streams; i++) { Console.WriteLine(); AVStream* stream = av_context->streams[i]; AVCodecParameters* codecpar = stream->codecpar; AVCodecContext* codec = stream->codec; Console.WriteLine($"Stream #0:{stream->index} {codecpar->codec_type} {codecpar->codec_id} (0x{codecpar->codec_tag.ToString("x")})"); if (codecpar->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { Console.Write($"{codecpar->width}x{codecpar->height}, {stream->codec->pix_fmt}, {(AVPixelFormat)codecpar->format}, {codecpar->color_primaries}, {((float)codec->framerate.num / codec->framerate.den):.00} fps"); Console.Write($", {stream->codec->pkt_timebase.den / stream->codec->pkt_timebase.num / 1000}k tbn"); float tbc = (float)stream->codec->time_base.den / stream->codec->time_base.num; if (tbc > 1000) { Console.Write($", {tbc / 1000}k tbc"); } else { Console.Write($", {tbc:.00} tbc"); } Console.WriteLine(); } else { Console.WriteLine($"{codecpar->sample_rate} Hz, {codecpar->channels} Channel(s), {codecpar->bit_rate / 1000} kb/s, {(AVSampleFormat)codecpar->format}"); } WriteMetadata(stream->metadata); } </pre> <br /> 위의 코드를 <a target='tab' href='https://www.sysnet.pe.kr/2/0/12947'>지난 글에서 설명한 4개의 스트림을 갖는 파일</a>을 입력으로 실행하면 다음과 같은 출력 정보를 얻을 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [metadata] major_brand = isom minor_version = 512 compatible_brands = isomiso2avc1mp41 encoder = Lavf58.45.100 [context-info] duration: 187.954 # of streams: 4 url: D:\media_sample\output2.mp4 start time: 0 bitrate: 3553.945 kb/s Stream #0:0 AVMEDIA_TYPE_VIDEO AV_CODEC_ID_H264 (0x31637661) 1920x1080, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P, AVCOL_PRI_BT709, 29.97 fps, 16k tbn, 59.94 tbc language = und handler_name = ISO Media file produced by Google Inc. vendor_id = [0][0][0][0] Stream #0:1 AVMEDIA_TYPE_AUDIO AV_CODEC_ID_AAC (0x6134706d) 48000 Hz, 2 Channel(s), 128 kb/s, AV_SAMPLE_FMT_FLTP language = eng handler_name = SoundHandler vendor_id = [0][0][0][0] Stream #0:2 AVMEDIA_TYPE_AUDIO AV_CODEC_ID_AAC (0x6134706d) 44100 Hz, 2 Channel(s), 128 kb/s, AV_SAMPLE_FMT_FLTP language = eng handler_name = ISO Media file produced by Google Inc. vendor_id = [0][0][0][0] Stream #0:3 AVMEDIA_TYPE_VIDEO AV_CODEC_ID_VP9 (0x39307076) 640x360, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P, AVCOL_PRI_BT709, 29.97 fps, 16k tbn, 16k tbc language = eng handler_name = VideoHandler vendor_id = [0][0][0][0] </pre> <br /> 이 정보를 ffprobe로 알아낸 것과 비교해 볼까요? ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > D:\media_sample> <span style='color: blue; font-weight: bold'>ffprobe output2.mp4</span> ...[생략]... libpostproc 55. 9.100 / 55. 9.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output2.mp4': <span style='color: blue; font-weight: bold'>Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.45.100</span> <span style='color: blue; font-weight: bold'>Duration: 00:03:07.95, start: 0.000000, bitrate: 3553 kb/s</span> <span style='color: blue; font-weight: bold'>Stream #0:0(und): Video: h264</span> (High) (avc1 / <span style='color: blue; font-weight: bold'>0x31637661</span>), <span style='color: blue; font-weight: bold'>yuv420p</span>(tv, <span style='color: blue; font-weight: bold'>bt709</span>), <span style='color: blue; font-weight: bold'>1920x1080</span> [SAR 1:1 DAR 16:9], 3070 kb/s, <span style='color: blue; font-weight: bold'>29.97 fps</span>, 29.97 tbr, <span style='color: blue; font-weight: bold'>16k tbn, 59.94 tbc</span> (default) <span style='color: blue; font-weight: bold'>Metadata: handler_name : ISO Media file produced by Google Inc. vendor_id : [0][0][0][0]</span> <span style='color: blue; font-weight: bold'>Stream #0:1(eng): Audio: aac</span> (LC) (mp4a / <span style='color: blue; font-weight: bold'>0x6134706D</span>), <span style='color: blue; font-weight: bold'>48000 Hz, stereo, fltp</span>, <span style='color: blue; font-weight: bold'>128 kb/s</span> (default) <span style='color: blue; font-weight: bold'>Metadata: handler_name : SoundHandler vendor_id : [0][0][0][0]</span> <span style='color: blue; font-weight: bold'>Stream #0:2(eng): Audio: aac</span> (LC) (mp4a / <span style='color: blue; font-weight: bold'>0x6134706D</span>), <span style='color: blue; font-weight: bold'>44100 Hz, stereo, fltp</span>, <span style='color: blue; font-weight: bold'>128 kb/s</span> (default) <span style='color: blue; font-weight: bold'>Metadata: handler_name : ISO Media file produced by Google Inc. vendor_id : [0][0][0][0]</span> <span style='color: blue; font-weight: bold'>Stream #0:3(eng): Video: vp9</span> (Profile 0) (vp09 / <span style='color: blue; font-weight: bold'>0x39307076</span>), <span style='color: blue; font-weight: bold'>yuv420p</span>(tv, <span style='color: blue; font-weight: bold'>bt709</span>), <span style='color: blue; font-weight: bold'>640x360</span>, 212 kb/s, SAR 1:1 DAR 16:9, <span style='color: blue; font-weight: bold'>29.97 fps</span>, 29.97 tbr, <span style='color: blue; font-weight: bold'>16k tbn, 16k tbc</span> (default) <span style='color: blue; font-weight: bold'>Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0]</span> </pre> <br /> 대충 유사하게 구할 수 있군요. 나머지 정보들은 시간이 지나면 천천히 해결이 되겠고. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> (2022-02-01: 업데이트)<br /> <br /> ffprobe의 출력 결과를 그대로 얻을 수 있는 av_dump_format 함수가 있군요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > int videoIndex = -1; int audioIndex = -1; { videoIndex = ffmpeg.av_find_best_stream(av_context, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, null, 0); audioIndex = ffmpeg.av_find_best_stream(av_context, AVMediaType.AVMEDIA_TYPE_AUDIO, -1, -1 /* 또는 videoIndex */, null, 0); ffmpeg.av_dump_format(av_context, videoIndex, filePath, 0); } </pre> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1892&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1907
(왼쪽의 숫자를 입력해야 합니다.)