# 14.1 -2 Transcode Video

이원규·2022년 7월 16일
0

Itube

목록 보기
41/46

Transcode Video

object url: 영상의 모든 정보를 담음. // event.datad에 binary data가 있는데 파일일 수도 있는 binary data에 createObjectURL을 이용해서 접근할 수 있어야함.

-> 밑의 사진은 videoFile = URL.createObjectURL(event.data); 의 videoFile 콘솔임.

우리가 원하는건 handelDownload를 누르면 영상을 눌러서 변환하는 것임.

ffmpeg사용법

const fs = require('fs');
const { createFFmpeg, fetchFile } = require('@ffmpeg/ffmpeg');

const ffmpeg = createFFmpeg({ log: true });

(async () => {
  await ffmpeg.load();
  ffmpeg.FS('writeFile', 'test.avi', await fetchFile('./test.avi'));
  await ffmpeg.run('-i', 'test.avi', 'test.mp4');
  await fs.promises.writeFile('./test.mp4', ffmpeg.FS('readFile', 'test.mp4'));
  process.exit(0);
})();

Transcode Video

1. recoder.js작성

import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";


const handleDownload = async() => {
  	//1 단계
    const ffmpeg = createFFmpeg({corePath: "/convert/ffmpeg-core.js" ,log: true});
    await ffmpeg.load(); // await사용: 사용자가 소프트웨어를 사용할 것이기 때문. 사용자가 JS가 아닌 코드를 사용하는 거임, 무언가를 설치해서. 우리 웹사이트에서 다른 소프트웨어를 사용하는 거임. 소프트웨어가 무거울 수 있기 때문에 기다려야함.
  
  	//2단계: ffmpeg에 파일 만들기 = 백엔드의 multer같은 존재. 실존하진 않아도 프론트엔드에 파일이 생김
  	ffmpeg.FS("writeFile", "recording.webm", await fetchFile(videoFile)); // 파일 생성 -> recording.webm은 생성하는 파일 이름, fetchFile -> 우리가 만든 videoFile(Blob파일에 접근할 수 있는 url로 만든 것임 즉, 이 데이터는 Blob이므로 binary data형식임.) 
    await ffmpeg.run("-i", "recording.webm", "-r", "60", "output.mp4"); // 파일 변환 과정. 가상 컴퓨터에 이미 존재하는 파일(방금 바로 윗줄 파일 생성해준 파일임.)(recording.webm)을 input으로 받는 것임. -> input을 output으로 변형하겠다. -i: input으로 받겠다는 뜻임.
  	
  	// 3단계: output.mp4 가져오기
  	const mp4File = ffmpeg.FS("readFile", "output.mp4"); // output파일 가져오기
    console.log(mp4File.buffer);
    const mp4Blob = new Blob([mp4File.buffer], {type:"video/mp4"});// 변환된 output파일의 ArrayBuffer(raw binary data buffer를 나타내는 object)를 아용하여 video의 mp4형태의 Blob(binary파일 형식)으로 만들어준다. blob으로 만들거기 때문에 input data를 binary형식으로 해줌.
    const mp4Url = URL.createObjectURL(mp4Blob); // 위에서 만든 Blob에 접근할 수 있도록 url부여
  
  	//변경
  	a.href = mp4Url;
    a.download = "MyRecording.mp4";
};

-> 실행하면 output파일 생성(메모리에 output.mp4라는 파일 생성)

2단계 : 우리가 브라우저 안에 있다는 생각을 멈춤. 눈을 감고 폴더와 파일로 가득찬 컴퓨터 안에 있다 생각하면서 이들을 맘대로 조종할 수 있는 컴퓨터를 브라우저에서 실행하는 신이 된다 생각. -> ffmpeg에 파일 만들기 = 백엔드의 multer같은 존재. 프론트엔드의 ffmpeg

3단계 : output.mp4 가져오기. 일단 output파일을 읽기 형식으로 가져온다. 그런 뒤, 해당 파일의 buffer중 raw binary data buffer를 나타내는 object인 즉, 한 마디로 우리 영상을 나타내는 bytes의 배열인 ArrayBuffer에 접근하는 것을 목적(mp4File.buffer하면 ArrayBuffer접근됨.)으로, 해당 파일의 버퍼를 video/mp4의 형태로 즉 binary데이터를 가진 형태인 Blob형태로 변환시켜준다. 이후 이 Blob을 createObjectUrl을 이용하여 브라우저 메모리 상에 저장을 해두고, 우리가 그 파일에 접근할 수 있는 URL을 준다.


ffmpeg.documedation.videoOptions

ffmpeg.FS(method, ...args): any/ ffmpeg.FS("파일 작성", "파일 이름", binarydata);
ffmpeg.wasm의 입출력 파일은 ffmpeg.wasm이 소비할 수 있도록 먼저 MEMFS에 저장해야 합니다.
https://github.com/ffmpegwasm/ffmpeg.wasm/blob/master/docs/api.md#ffmpegfsmethod-args-any

fetchFile(media): Promise
다양한 리소스에서 파일을 가져오기 위한 도우미 기능입니다. 때로는 처리하려는 비디오 / 오디오 파일이 원격 URL과 로컬 파일 시스템의 어딘가에 있을 수 있습니다.이 도우미 함수는 파일로 가져오고 ffmpeg.wasm이 사용할 Uint8Array 변수를 반환하는 데 도움이 됩니다. fetch = url파일 실행(get / post), file: 파일 형태로 된 url fetch처리 한다는 뜻임.
https://github.com/ffmpegwasm/ffmpeg.wasm/blob/master/docs/api.md#fetchfilemedia-promise

ffmpeg.load
ffmpeg.load()를 호출하면 기본적으로 http://localhost:3000/node_modules/@ffmpeg/core/dist/를 검색하여 필수 파일을 다운로드합니다. (ffmpeg-core.js, ffmpeg-core.wasm, ffmpeg-core.worker.js). 해당 파일이 거기에 제공되었는지 확인해야 합니다. 해당 파일이 다른 위치에 있는 경우 호출할 때 기본 동작을 다시 작성할 수 있습니다.
https://github.com/ffmpegwasm/ffmpeg.wasm#why-it-doesnt-work-in-my-local-environment

binarydata: 이진수(0과 1)로 이루어진 데이터

fmpeg.run : 가상 컴퓨터에 이미 존재하는 파일을 input으로 받는 것임. -> input을 output으로 변형하겠다. -i: input으로 받겠다는 뜻임. / "r", "60" : 영상을 초당 60프레임으로 인코딩 해주는 명령어.


MEMFS에서 데이터 읽기
ffmpeg.FS('readFile', 'video.mp4');
https://github.com/ffmpegwasm/ffmpeg.wasm/blob/master/docs/api.md#ffmpegfsmethod-args-any

buffr

Uint8Array (양의 정수 8비트 배열)
Uint8Array 형식 배열은 8비트 부호 없는 정수 배열을 나타냅니다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array

ArrayBuffer
ArrayBuffer 객체는 raw binary data buffer를 나타내는 object이다. 한 마디로 우리 영상을 나타내는 bytes의 배열임. 다른 언어에서는 종종 "byte array"이라고 하는 byte array입니다. arrayBuffer를 사용하고 싶다면 buffer에 접근해야 된다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer

Blob
Blob: binary정보를 가지고 있는 파일.
자바스크립트 세계의 파일과 같은거. 파일같은 객체를 만듦. 객체는 파일류의 불변하는 미가공 데이터를 나타냅니다. 텍스트와 이진 데이터의 형태로 읽을 수 있으며, ReadableStream으로 변환한 후 그 메서드를 사용해 데이터를 처리할 수도 있습니다.
https://developer.mozilla.org/ko/docs/Web/API/Blob

2. error해결

  1. http://localhost:4000/node_modules/@ffmpeg/core/dist/ffmpeg-core.js 404 (Not Found) 또는
    createFFmpegCore is not defined 오류 해결 방법

->
1️⃣ server.js
app.use("/convert", express.static("node_modules/@ffmpeg/core/dist"));
2️⃣ recorder.js
const ffmpeg = createFFmpeg({
corePath: "/convert/ffmpeg-core.js",
log: true,
});

  1. Uncaught (in promise) ReferenceError: SharedArrayBuffer is not defined 오류 해결 방법
    FFmpeg를 실행했을 때, 콘솔창에 위와 같은 오류가 난다면 server.js에 app.set()아래에 함수를 추가해주시면 됩니다.

->
오류 원인 : SharedArrayBuffer는 cross-origin isolated된 페이지에서만 사용할 수 있습니다. 따라서 ffmpeg.wasm을 사용하려면 Cross-Origin-Embedder-Policy: require-corp 및 Cross-Origin-Opener-Policy: same-origin를 header에 설정해 자체 서버를 호스팅해야 합니다.
https://github.com/ffmpegwasm/ffmpeg.wasm/issues/263

// server.js
app.use((req, res, next) => {
	res.header("Cross-Origin-Embedder-Policy", "require-corp");
	res.header("Cross-Origin-Opener-Policy", "same-origin");
next();
});

FFmpeg Usage
https://github.com/ffmpegwasm/ffmpeg.wasm#usage

FFmpeg API
https://github.com/ffmpegwasm/ffmpeg.wasm/blob/master/docs/api.md#api

profile
github: https://github.com/WKlee0607

0개의 댓글