FFmpeg로/에서 데이터를 손실 없이 파이프할 수 있는 방법은 무엇입니까?

FFmpeg로/에서 데이터를 손실 없이 파이프할 수 있는 방법은 무엇입니까?

FFmpeg의 한 인스턴스에서 다른 인스턴스로 스트림을 파이프했지만 중간 스트림에서 압축이 사용되었기 때문에 최종 결과는 좋지 않았습니다. 이를 방지하려면 무손실 파이프가 필요하며 오디오와 비디오를 모두 포함하고 싶습니다.

나는 이 문제에 대한 답이 하나 이상 있다고 생각하므로, 솔루션(파이핑할 수 있는 호환 컨테이너 및 코덱)의 전체 목록을 제공하는 사람에게 보너스 포인트가 주어집니다. 보너스 포인트는 자막과 같은 다른 데이터를 설명하는 모든 사람에게도 제공됩니다.

편집: 적합한 코덱/컨테이너 조합을 찾고 있습니다. 왜 사람들이 그것을 알아내는 데 어려움을 겪는지 모르겠습니다. 이미 파이프를 사용했고 이제는 무손실이 필요하다고 말했기 때문입니다.

자만하지 않고 이것을 어떻게 설명해야 할지 모르겠지만, 이것은 FAQ 사이트입니다. 매우 구체적인 답변이 필요한 질문을 하는 것은 자신의 문제를 검색 엔진에 입력하여 이 사이트를 방문하는 수백만 명의 사용자에게 도움이 되지 않습니다. 내 질문은 내가 하고 있는 일, 작동하지 않는 이유, 이것이 유일한 옵션인 이유를 설명하는 내러티브와 코드의 벽으로 모든 사람의 주의를 산만하게 하지 않고 FFmpeg 인스턴스 간에 데이터를 무손실로 연결해야 하는 다른 사람을 돕기 위해 고안되었습니다.

답변1

ffmpeg비디오와 오디오를 무손실 로 파이프하는 방법ffmpeg

질문자의 요구사항:

  • 한 인스턴스에서 ffmpeg다른 인스턴스로 무손실 파이프
  • 그것이 오고 가는지는 중요하지 않아/dev/null

예:

ffmpeg -s 1280x720 -f rawvideo -i /dev/zero -ar 48000 -ac 2 -f s16le -i \
/dev/zero -c copy -f nut pipe:1 | ffmpeg -y -i pipe:0 -c copy -f nut /dev/null

누군가가 이것을 할 이유가 없습니다.또한 하나의 프로세스를 사용하여 원하는 작업을 수행 할 수 있는 시점 ffmpeg까지 파이프할 이유가 거의 없습니다 .ffmpegffmpeg

옵션의 기능:

  • -s 1280x720 -f rawvideo– 이후 입력을 설명하는 옵션/dev/zero일반적인 입력 형식이 아니므로 이러한 추가 옵션이 필요합니다.

  • -i /dev/zero– 비디오 입력. 이 예에서는 "nothing"에서 비디오 스트림을 생성하는 데 사용됩니다. 질문자가 사용 중인 입력에 대한 정보 제공을 거부했기 때문에 이 예에서 사용되었습니다.

  • -ar 48000 -ac 2 -f s16le– 이후 입력을 설명하는 옵션/dev/zero일반적인 오디오 형식이 아닙니다.

  • -i /dev/zero– 오디오 입력. 이 예에서는 "nothing"에서 오디오 스트림을 생성하는 데 사용됩니다.

  • -c copy스트림 복사, 또는 재다중화, 입력을 출력으로. 재인코딩이 수행되지 않으므로 프로세스가 손실되지 않습니다. 질문자가 스트림 복사를 허용하는지 여부는 알 수 없습니다. 대신 다시 인코딩하는 것이 바람직할까요?

  • -f nutffmpeg– 파이프에 사용할 형식을 알려주어야 합니다 . Nut는 컨테이너 형식입니다. ffmpeg -formats전체 목록을 보려면 를 참조하세요 . 또 다른 유연한 형식은 이지만 -f matroska, 질문자의 추가 정보 없이는 사용할 적절하거나 구체적인 출력 컨테이너 형식을 제안하는 것은 불가능합니다.

  • pipe:1- 사용pipe규약stdout으로 출력합니다. 또는 숫자를 생략할 수 있으며(단지 pipe:) 기본적으로 stdout 파일 설명자는 쓰기에 사용되고 stdin은 읽기에 사용됩니다.

답변2

이전 답변의 일부에서 내가 배운 방법은 rawvideo비디오 코덱, pcm_s16le오디오 코덱 및 FFmpeg nut래퍼를 사용하여 스트림을 인코딩하는 것입니다. nutFFmpeg 외부의 주요 프로그램에서는 지원되지 않지만 프로세스 간에 데이터를 효율적으로 연결하는 데 필요한 압축되지 않은 형식을 지원할 수 있는 제가 현재 알고 있는 유일한 컨테이너입니다.

이 인코딩에 대한 인수는 다음과 같습니다.

... -c:v rawvideo -c:a pcm_16le -f nut - ...

일부 오디오는 24비트 이상의 샘플로 저장되므로 대신 pcm_24le또는 다른 형식을 사용해야 합니다. 압축되지 않은 오디오 형식의 전체 목록은 다음을 실행하여 나열됩니다 ffmpeg -codecs(목록에서 검색해야 함). 오디오의 샘플 크기를 모르는 경우 를 사용해 pcm_16le도 눈에 띄는 품질 저하가 발생하지 않습니다.

파이프의 수신 끝에서 입력을 표준 입력으로 설정하면 ffmpeg가 형식을 감지하고 스트림을 디코딩합니다.

... ffmpeg -i - ...

이 답변의 줄임표(...)는 코드의 일부가 아닙니다. 여기에 코드가 들어갑니다. 단독 하이픈(-)은 FFmpeg가 나타나는 위치에 따라 표준 입력 또는 표준 출력을 사용하도록 지시합니다.

업데이트:

나는 이것을 개선하기 위해 간단한 실험을 시도했고 더 나은 컨테이너는 AVI인 것 같습니다. 왜냐하면 다른 프로그램이 그것을 이해할 것이기 때문입니다(적어도 VLC는 이해할 것입니다).

... -c:v rawvideo -c:a pcm_16le -f avi - ...

이는 호환성이 추가된 이전 버전과 정확히 동일하게 작동합니다.

질문은 모든 사람에게 도움이 되어야 한다는 주장에도 불구하고, 돌이켜보면 많은 상황에서 도움이 되지 않는 질문을 게시한 것을 후회했습니다. 이렇게 하면 답변이 더 유용해집니다.

답변3

다른 답변의 한 가지 문제점은 s16le이 아닌 pcm_s16le이라는 것입니다. 또한 중복된 매개변수가 많이 포함되어 있습니다.

파이프에서 flac 대신 pcm을 사용하겠습니다. 처리하는 데 훨씬 적은 시간이 걸리기 때문입니다(PCM은 원시 오디오이고 FLAC는 인코딩하는 데 많은 시간이 걸립니다).

어쨌든, 내가 할 방법은 다음과 같습니다.

ffmpeg -i <input video file/stream> -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -f rawvideo -i - -vcodec <video output codec> -acodec <audio output codec> -vb <video bitrate if applicable> -ab <audio bitrate if applicable> <final-output-filename>

이것은 내가 마지막으로 시도했을 때 효과가 있었지만 내 목표는 ffmpeg를 ffplay로 파이프하는 것이었습니다. 이는 약간 다른 프로세스입니다.

예:

이는 ffmpeg의 비디오를 원시 비디오 출력 및 16비트 리틀 엔디안 PCM으로 다른 인스턴스로 파이프합니다(24비트 PCM이 없으면 둘 다 무손실이며 .로 대체됩니다 pcm_s24le.) 그런 다음 fraunhoefer를 사용하여 두 번째 인스턴스에서 이를 h.264로 변환합니다. Android 프로젝트의 AAC 라이브러리( libfaacffmpeg 빌드에 더 일반적으로 포함됩니다. 대신 이 라이브러리로 대체할 수 있습니다.)

ffmpeg -i montypythonsflyingcircus-s1e1.avi -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -i - -vcodec libx264 -acodec libfdk_aac -vb 1200k -ab 96k mpfc-s1e01-output.mkv

자막이 파이프되지 않으면 언제든지 SRT로 추출한 다음 나중에 다시 다중화하거나 위의 파이프에 쉽게 추가할 수 있습니다.

관련 정보