mp3를 mp4로 변환하는 방법을 찾으면서 생각해본 방법은 두가지였다.
1. video tag에 mp3를 달았을떄 동영상 컨트롤러처럼 나오느냐?
2. FFMPEG을 통한 MP3 -> MP4 변환
1의 경우에는 된다면 간단하니 정말 좋고 안되면 말면 식으로 생각해본 방법이었는데, 역시나? 안되었다.
그래서 어쩔수 없이 FFMPEG을 통해서 변환하는 방법을 사용하기로 하였다.
근데 내가 만들고 싶은 것은
MP3파일에 사진을 붙여 MP4 파일을 만드는 홈페이지고, 브라우저 상에서 운용되어야하였다.
따라서 웹어셈블리 형식으로 포팅된 FFMPEG.WASM이란 라이브러리를 사용하기로 하였다.
FFMPEG.WASM이란
순수 자바스크립트와 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);
})();
기본적인 코드 형태는 이렇다.
ffmpeg를 로드하고, FS을 통해 파일을 읽거나 쓴다.
FS는 MEMFS로 먼저 저장된 다음 Emscription의 FS METHOD을 통해 입출력한다.
MEMFS는 테스트할떄 사용할 수 있는 In-memory 가상 filesystem이다.
FS.('writeFile')을 통해 가상 파일시스템인 MEMFS에 저장을 하고 그것에서 실제 ffmpeg을 실행하고
저장한 결과를 FS.('readFile')을 통해서 다시 MEMFS에서 가져오는 방식인것 같다
COEP와 COOP
발생했던 문제는 바로 공식문서에도 쓰여있던
SharedArrayBuffer is only available to pages that are cross-origin isolated. So you need to host
your own server with Cross-Origin-Embedder-Policy: require-corp and Cross-Origin-Opener-Policy: same-origin headers to use ffmpeg.wasm.
FFMPEG.WASM에 사용되는 SharedArrayBuffer는 cross-origin isolated된 페이지에만 사용할 수 있다는 것이다.
Emscription에서 pthread 코드에서 SharedArrayBuffer를 사용하기 떄문에 발생하는 문제다.
필자같은 경우에는 Vercel을 통해서 deploy할 것이기 떄문에
vercel.json을 생성하여
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "cross-origin-opener-policy",
"value": "same-origin"
},
{
"key": "cross-origin-embedder-policy",
"value": "require-corp"
}
]
}
]
}
로 관련 헤더들을 설정해주었다.
이 헤더들은 cross-origin 문서에서 로드되도록 허락되지 않은 리소스들이나 iframe의 로딩을 막아준다. 이런 설정이 없다면 강력한 기능들을 안전하게 사용한다는 보장이 없다.
self.crossOriginIsolated를 통해 상태를 알 수 있다.
webpack
단순하게 가고 싶었기에 별도의 보일러플레이트없이 만들었기에 webpack 설정을 처음으로 시작부터 끝까지 하게 되었다.
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'public'),
},
};
entry는 번들링의 시작이 될 부분을 의미한다.
Mutiple entry를 가져 여러개의 번들로 분할하고 병렬, 혹은 요청마다 다른 번들들을 제공할수도 있다.
output은 번들의 결과를 내뱉는 곳이며 이것은 import하여 html에 불러오는 것으로 전체 자바스크립트 코드를 불러오는 것과 동일한 것이다. 리액트도 동일한 방식.
시간날때 읽어볼것들(엔트리 포인트와 코드 스플리팅)
https://webpack.js.org/concepts/entry-points/
https://webpack.kr/guides/code-splitting/
Reference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
https://github.com/simonc/memfs
'TIL' 카테고리의 다른 글
TIL 2021-11-16 ARP, cross-env, Tailwind CSS with Webpack (0) | 2021.11.17 |
---|---|
TIL 2021-11-15 ICMP 2, Proxy ARP (0) | 2021.11.15 |
TIL 2021-11-13 Tailwind CSS// input type file (0) | 2021.11.13 |
TIL 2021-11-11 Puppeteer와 Cheerio (0) | 2021.11.11 |
TIL 2021-11-10 ICMP 1 (0) | 2021.11.10 |