-
[React] ffmpeg.wasm 메모리 누수 문제 해결Javascript & TypeScript 2021. 5. 8. 16:11반응형
몇칠 전 ffmpeg.wasm 패키지를 소개했던 적이 있다. (ddochea.tistory.com/147) 웹 클라이언트만으로 미디어 파일에 대한 인코딩/디코딩 기술을 사용할 수 있다는 장점과 함께, memory leak이 발생하고 있는 이슈가 있어, 실제 서비스 개발에 도입하기엔 무리가 있을 것 같다고 했었다.
그리고 나서 오늘 좀 더 확인해보는 시간을 가졌는데, thread 관련 문제가 있는건 맞지만, 메모리 부분은 내가 코딩을 잘못해서 생긴 것을 깨닫게 되었다.
이 문제는 내가 만든 예제 뿐만 아니라, 공식사이트에 소개하고 있는 React 예제도 같은 문제가 있다.
아래 코드 공식사이트 예제 코드이다.
import React, { useState } from 'react'; import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'; import './App.css'; function App() { const [videoSrc, setVideoSrc] = useState(''); const [message, setMessage] = useState('Click Start to transcode'); const ffmpeg = createFFmpeg({ log: true, }); const doTranscode = async () => { setMessage('Loading ffmpeg-core.js'); await ffmpeg.load(); setMessage('Start transcoding'); ffmpeg.FS('writeFile', 'test.avi', await fetchFile('/flame.avi')); await ffmpeg.run('-i', 'test.avi', 'test.mp4'); setMessage('Complete transcoding'); const data = ffmpeg.FS('readFile', 'test.mp4'); setVideoSrc(URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }))); }; return ( <div className="App"> <p/> <video src={videoSrc} controls></video><br/> <button onClick={doTranscode}>Start</button> <p>{message}</p> </div> ); } export default App;
사실 조금만 생각해보면 해결되는 문제였다. React 내부 컴포넌트에 일반 변수로 선언된 ffmpeg 객체가 매번 내부에서 이벤트가 발생할때마다 새로 생성된다는걸 기억한다면 말이다.
수정된 코드는 아래와 같다.
import React, { useState } from 'react'; import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'; import './App.css'; const ffmpeg = createFFmpeg({ log: true, }); // App 컴포넌트 밖으로 선언 function App() { const [videoSrc, setVideoSrc] = useState(''); const [message, setMessage] = useState('Click Start to transcode'); const doTranscode = async () => { setMessage('Loading ffmpeg-core.js'); if(!ffmpeg.isLoaded()){ await ffmpeg.load(); } setMessage('Start transcoding'); ffmpeg.FS('writeFile', 'test.avi', await fetchFile('/flame.avi')); await ffmpeg.run('-i', 'test.avi', 'test.mp4'); setMessage('Complete transcoding'); const data = ffmpeg.FS('readFile', 'test.mp4'); setVideoSrc(URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }))); }; return ( <div className="App"> <p/> <video src={videoSrc} controls></video><br/> <button onClick={doTranscode}>Start</button> <p>{message}</p> </div> ); } export default App;
지난시간에 Github에 올려둔 소스는 React의 Context를 이용하여 해결했다.
반응형'Javascript & TypeScript' 카테고리의 다른 글
[Vite] 로컬 개발환경에서 https 도메인 설정하기 (0) 2022.12.24 [Svelte] 스벨트에서의 event capture와 bubbling (0) 2022.12.17 [Javascript] 브라우저에서 사용하는 인코딩 및 디코딩 패키지 ffmpeg.wasm 소개 (2) 2021.05.05 [Javascript Event] Drop 이벤트에 preventDefault, stopPropagation를 적용해도 동작하지 않는 현상 해결 (0) 2021.04.27 [React] React Router를 적용해도 첫 메인페이지("/") 위치만 표시되는 현상 해결법 (0) 2021.04.26