Snowpack으로 WASM 시작하기
Source
이 글은 아래 튜토리얼을 공부하고 분석한 글이다. 이 글이 도움이 되었다면 내 저장소 대신 아래 저장소에 스타를 눌러주자.
과정
- 다음 문장을 통해
create-snowpack-app
으로 gif-converter라는 프로젝트를 생성한다.
npx create-snowpack-app gif-converter --template @snowpack/app-template-react
- 다음 문장을 통해
ffmpeg.wasm
을 설치한다. (실제 WASM 파일은 사용자의 웹페이지에서는 CDN을 통해 async하게 로딩됨. 여기서 설치하는 것은 Wrapper인 것 같다.)
npm install @ffmpeg/ffmpeg @ffmpeg/core
- 그 다음
snowpack
을 설치한다.
npm install snowpack --save-dev
- 다음 명령어로 테스트 가능하다. snowpack을 위 문장으로 설치하는 대신
npm i -g snowpack
으로 글로벌하게 설치했다면snowpack dev
를 하면 된다.
npm start
- src/App.jsx
import React, { useState, useEffect } from 'react'
import './App.css'
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
const ffmpeg = createFFmpeg({ log: true })
function App() {
const [ready, setReady] = useState(false)
const [video, setVideo] = useState()
const [gif, setGif] = useState()
const load = async () => {
await ffmpeg.load()
setReady(true)
}
useEffect(() => {
load()
}, []) // blank [] makes it run once.
const convertToGif = async () => {
// Write the file to memory
ffmpeg.FS('writeFile', 'test.mp4', await fetchFile(video))
// Run the FFMpeg command
await ffmpeg.run(
'-i', // input flag
'test.mp4', // video source input
'-t', // time flag
'2.5', // for 2.5 seconds
'-ss', // starting secont flag
'2.0', // offset for 2 seconds
'-f', // file
'gif', // encode as gif file
'out.gif' // write file to out.gif
)
// Read the result
const data = ffmpeg.FS('readFile', 'out.gif')
// Create a URL
const url = URL.createObjectURL(new Blob([data.buffer], { type: 'image/gif' }))
setGif(url)
}
return ready ? (
<div className="App">
{video && <video controls width="250" src={URL.createObjectURL(video)}></video>}
<input type="file" onChange={(e) => setVideo(e.target.files?.item(0))} />
<h3>Result</h3>
<button onClick={convertToGif}>Convert</button>
{gif && <img src={gif} width="250" />}
</div>
) : (
<p>Loading...</p>
)
}
export default App
- FFMpeg는 in-memory file system을 사용한다.
- 다음과 같은 형태의 JS 문법을 사용하여
gif
가 JS 기준 false(null, undefined, false...)가 아닐 때만 렌더링되도록 만들 수 있다.
{
gif && <img src={gif} width="250" />
}
GitHub Pages에 Snowpack App 호스팅 및 시행착오
- 기존에 사용하던 방식으로 GitHub Pages에 띄우려고 했다. 그런데
_dist_
폴더의index.html
에서 404 Not Found가 발생했다. - 빌드하면서
docs
폴더 및build
폴더를 초기화하는 스크립트 추가 (기존 방식에서도 포함하고 있는 기능인데 처음에는 단순히 폴더명을build
에서docs
로 바꾸는 기능만 넣고 이 부분을 포함하지 않았다.) 문제가 해결되지 않았다. gh-pages
를 사용해보았다. 문제가 해결되지 않았다.- 그 다음
touch docs/.nojekyll
해보았다. 작동하지 않았다. (나중에 알게 됐지만 이게 해결책이었다. GitHub Pages가 Environment 탭에서는 Deploy 되었다고 나타나는데 반해 실제로는 업데이트되지 않아서 이게 해결책이 아닌 줄 알았다.) - 또 다음과 같이
snowpack.config.js
에서baseUrl
을 변경해주었다. (이것도 필요한 해결책이었다. 나의 GitHub Pages는 subdirectory에 호스팅하기 때문에 이와 같은 옵션이 필요하다. 참고 링크 1, 참고 링크 2)
buildOptions: {
baseUrl: '/ffmpeg-wasm-gif-converter-study/',
},
- Production 폴더의
_dist_
디렉토리의 이름을static
으로 변경했다. 이는 snowpack.config.js에서 다음 코드를 변경함으로써 가능하다. (실제로는 불필요한 변경이었다.)
mount: {
public: '/',
src: '/static',
},
- 이는 또한 public/index.html에서 src를 변경해주었다. 위의 Discussion Post들을 볼 때 여기를
%PUBLIC_URL%
으로 해야하는 것 같은데, 일단 ./static/index.js을 사용했다. 이를 통해서 index.html은 로딩되었다.
<script type="module" src="./static/index.js"></script>