이 명령을 사용하여 프레임을 추출하면 다음과 같은 사실이 나타났습니다.
ffmpeg -i sample_nosound.mp4 $filename%03d.jpg
기본적으로 fps를 기준으로 추출됩니다. ffmpeg -i sample_nosound.mp4
비디오는 6fps의 프레임 속도로 표시되므로 1630jpg 프레임을 추출합니다. 여기서 1630/6 = 271.6초는 전체 비디오 지속 시간의 4:32와 같습니다.
그러나 1630 jpg 프레임의 전체 크기는 13MB입니다.
$ du -h extracted_jpg_folder
13M extracted_jpg_folder
, mp4의 파일 크기는 1.8MB로 전체 프레임 크기보다 훨씬 작습니다.
$ ls -la sample_nosound.mp4
-rw-rw-r-- 1 xiaobai xiaobai 1814889 Feb 13 15:42 'sample_nosound.mp4'
이는 ffmpeg가 반복되는 프레임의 fps 정보를 참조하여 프레임을 추출한다는 것을 의미합니다.
그래서 내 질문은 fps에 의존하지 않고 "저장된 프레임"을 통해 ffmpeg 추출 프레임을 어떻게 만들 수 있습니까?
전체 프레임 크기를 mp4 파일 크기와 거의 동일하게 얻을 수 있기를 바랍니다.
mp4에는 일부 메타데이터가 포함될 수 있으므로 정확한 파일 크기 일치를 기대하지는 않습니다.
출력 ffprobe -i sample_nosound.mp4
:
ffprobe version 3.4.4-0ubuntu0.18.04.1 Copyright (c) 2007-2018 the FFmpeg developers
built with gcc 7 (Ubuntu 7.3.0-16ubuntu3)
configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
WARNING: library configuration mismatch
avcodec configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared --enable-version3 --disable-doc --disable-programs --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libtesseract --enable-libvo_amrwbenc
libavutil 55. 78.100 / 55. 78.100
libavcodec 57.107.100 / 57.107.100
libavformat 57. 83.100 / 57. 83.100
libavdevice 57. 10.100 / 57. 10.100
libavfilter 6.107.100 / 6.107.100
libavresample 3. 7. 0 / 3. 7. 0
libswscale 4. 8.100 / 4. 8.100
libswresample 2. 9.100 / 2. 9.100
libpostproc 54. 7.100 / 54. 7.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'sample_nosound.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.83.100
Duration: 00:04:32.00, start: 0.000000, bitrate: 53 kb/s
Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt470bg/bt709/bt709), 640x330 [SAR 1:1 DAR 64:33], 53 kb/s, 6 fps, 6 tbr, 12288 tbn, 12 tbc (default)
Metadata:
handler_name : VideoHandler
답변1
질문을 이해하면 비디오에서 프레임을 추출하고 싶습니다. 각 프레임은 별도의 파일에 저장되어야 합니다. 모든 파일 크기의 합은 비디오 파일 크기와 일치해야 합니다. 이는 특정 동영상에만 작동합니다. 폭넓게 설명하려고 노력하겠습니다.
긴 이야기 짧게
h264로 인코딩된 비디오에서는 동일한 시각적 품질과 파일 크기의 프레임을 추출할 수 없습니다.
혼란스러운 비디오 컨테이너 형식
이 예의 비디오 파일은 MP4 파일입니다. MP4는 비디오 데이터의 컨테이너입니다. 그러나 컨테이너의 유형은 실제 내용에 대해 실제로 아무 것도 말해주지 않습니다. 사실 종류도 다양해요비디오 형식zip 아카이브(또는 PDF 파일)처럼 MP4 파일에 상주할 수 있습니다.
다양한 종류의 영상이 있어요
비디오는 이미지의 연속입니다. 이러한 이미지를 비디오 스트림에 저장하는 방법(인코딩)과 나중에 읽는 방법(디코딩)은 여러 가지가 있습니다. 이러한 알고리즘은 종종 호출됩니다.코덱.
모든 코덱이 압축되는 것은 아닙니다. 이 예에서는 h264가 코덱입니다. 기본적으로 h264 인코더는 한 프레임과 다음 프레임 간의 차이를 계산합니다. 인코더는 차이가 작은 경우에만 차이를 저장합니다. 실제 프레임이 삭제됩니다. 첫 번째 프레임만 완전한 이미지로 저장됩니다. 이는 많은 공간을 절약하며 압축 전략 중 하나입니다. h264 디코더는 저장된 차이점을 이전 프레임에 적용하여 원본 프레임을 다시 생성합니다.
보시다시피 비디오의 프레임은 서로 종속되어 있습니다. 개별 파일을 원한다면 독립적이기를 원합니다. 이는 항상 각 단일 프레임에 대한 전체 정보를 저장해야 함을 의미합니다. 이는 단순히 기존 데이터를 가져와 파일에 복사할 수 없고 대신 비디오를 다시 인코딩해야 함을 의미합니다. 이 과정에서 전체 파일 크기가 증가해야 합니다.
다양하게 읽을 수 있어요비디오 압축의 사진 유형, 특히 "차이에 기초하여"인터프레임또는비디오 압축의 일반 개요.
h264는 JPEG가 아닙니다.
개별 이미지에 대해 이야기하더라도. JPEG는 소위 말하는 것을 사용합니다.이산 코사인 변환. H.264유사하지만 개선된 버전을 사용하세요. 즉, JPEG는 h264만큼 효율적으로 압축할 수 없습니다. 그런데 다음을 사용하여 h264 압축 이미지를 파일에 넣을 수 있습니다.반(이것은 본질적으로 단일 프레임 비디오와 같습니다).
'그것이 전적으로 사실은 아니지만 지금은 간단하게 유지하고 싶습니다. 실제로는 "장면의 첫 번째 프레임"과 비슷합니다. 세부 사항을 알고 싶다면
인코더가 각 장면의 시작 부분을 인식합니다(영화 촬영법에서는 이를 종종 "컷"이라고 함). 프레임 간 차이는 매우 크기 때문에 압축에 도움이 되지 않습니다. 인코더는 "차이 기반" 인터 프레임을 사용하지 않기로 결정했습니다. 대신 전체 그림을 사용합니다(이를 "인트라프레임", "키프레임"이라고도 함).
기술적인 이유도 있습니다. 프레임 내에서만 비디오를 검색할 때 빠르게 이동할 수 있습니다. 따라서 인트라 프레임도 때때로(실제 비디오 콘텐츠에 관계없이) 스트림에 추가됩니다. 일반적으로 비디오에는 초당 하나의 인트라 프레임이 있습니다.
이제 우리는 비디오 압축에 대해 많은 것을 알고 있습니다. 이 비디오에서는 몇 가지 사항을 보여줍니다.
이 비디오에는 파일 손상으로 인해 인트라프레임이 없습니다. 디코더는 어느 정도 성공적으로 재생합니다. 누락된 영상에는 여성이 옆을 바라보고 있는 모습이 나타날 수 있습니다. 이제 그녀가 고개를 돌리면 디코더에는 일부 동작 정보를 포함하는 프레임 사이의 데이터만 있습니다. 여자가 머리 옆에 얼굴을 대고 끝난 것 같습니다. 그 사이 한 남자가 배경을 가로질러 걸어간다. 누락된 프레임에 사람이 나오지 않아서 괜찮아 보입니다.