본문 바로가기

코딩/Today I Learn

01/04 공부2

728x90

자바스크립트로 녹화기능 만들기 

js에 recoder.js파일 생성 후 

webpack.config.js에

module.exports ={
    entry: {
        main: "./src/client/js/main.js",
        videoPlayer: "./src/client/js/videoPlayer.js",
        recoder: "./src/client/js/recoder.js",
    },

설정후 npm run dev:assets로 재시작하면 

assets/js/recoder.js 파일이 생성됨 

 

 

 

MediaDevices //녹음 녹화에 접근하는 속성
https://developer.mozilla.org/ko/docs/Web/API/MediaDevices

getUserMedia()
https://developer.mozilla.org/ko/docs/Web/API/MediaDevices/getUserMedia

constraints
요청할 미디어 유형과 각각에 대한 요구사항을 지정하는 MediaStreamConstraints 객체.
constraints 매개변수는 두 개의 구성 요소, video와 audio를 가지는 객체로, 요청할 미디어 유형에 대해 설명합니다. 둘 중 적어도 하나는 지정해야 합니다.

 

사용자가 수락하게되면 stream을 받게된다.

비디오 미리보기 

 

전체 코드 

upload .pug 에 video#preview추가 

 

 

const startBtn = document.getElementById("startBtn");
const video = document.getElementById("preview");
const handleStart = async() =>{
    const stream = await navigator.mediaDevices.getUserMedia({ //stream으로 카메라에 잡힌 부분을 미리보기 할 수 있다. 이 것을 video elment에 담아보자 
        audio:false,
        video:{width:200, height:300},
    }); 
  video.srcObject = stream; //html의 src와 다름 stream(0과1로이루어진 데이타인데)을 위해 사용함 MediaStream, MediaSource,Blob,File를 실행할 때 video에 주는 무언가
    video.play();
}
startBtn.addEventListener("click", handleStart)ansyc await에대한  regenerator 에러 뜸 --> 

프론트엔드에서 async await 사용하려면 regenerator설치하거나 or 그냥 promise 문법으로 사용 

 

regenerator-runtime
npm i regenerator-runtime
import regeneratorRuntime from "regenerator-runtime";

recorder.js보단 main.js에 import 하여  //main.js는 base.js에 script src로 불러옴

base.pug에 script 불러와서 모든 async await에 사용 할 수있도록

 

 

pug

div

  video#preview

  btn#startBtn Start Recording

 

지금까지는 눌러서 미리보기를 실행했는데

미리보기는 미리 실행되고 눌르면 녹화가 되는 방식을 구현해 볼 것임

const init= async() =>{
    const stream = await navigator.mediaDevices.getUserMedia({ 
        audio:false,
        video:{width:200, height:300},
    }); 
  video.srcObject = stream; 
    video.play();
}

init(); //init으로 이름 변경하고 기본으로 시작하게해 

------

하나의 버튼에 두개 이벤트 등록

const hanldeStop = () =>{
    startBtn.innerText = "Start Recording";
    startBtn.removeEventListener("click",hanldeStop);
    startBtn.addEventListener("click", handleStart);

}

const handleStart= () => {
    startBtn.innerText ="Stop Recording";

    startBtn.removeEventListener("click", handleStart);

    startBtn.addEventListener("click", handleStop);

}

------

녹화하기 MediaRecorder();

비디오든 오디오든 녹화하고mp4등으로 포맷을 저장할 수있음

녹화하고 stream으로 전달해보자 

 

handleStart function에 

const recorder = new MaidnRecorder(stream); 녹화하고 싶지만 

 

const init= async() =>{
    const stream = await navigator.mediaDevices.getUserMedia({ 
        audio:false,
        video:{width:200, height:300},
    }); // 다른 함수에 있는 const stream에 접근 할 수 없다.

 

 

let stream; // 그래서 빈 변수 let으로 외부에 지정해놓고  
const handleStart= () => {
    startBtn.innerText ="Stop Recording";
    startBtn.removeEventListener("click",handleStart);
    startBtn.addEventListener("click", hanldeStop);
    const recorder = new MediaRecorder(stream);  // MediaRecorder event를 사용하지 않으면 소용없는 코드 
    recorder.start();                                            // 
}

const init = async() =>{
     stream = await navigator.mediaDevices.getUserMedia({ //const stream이아니고 stream 업데이트 
        audio:false,
        video:{width:200, height:300},
    }); 
    video.srcObject = stream;
    video.play();
}t);

 

-----

 

const handleStart= () => {
    startBtn.innerText ="Stop Recording";
    startBtn.removeEventListener("click",handleStart);
    startBtn.addEventListener("click", hanldeStop);
    const recorder = new MediaRecorder(stream);
    recorder.ondataavailable = (e) =>{ //녹화가 멈추면 발생되는 이벤트 
        console.log("recording done");
        console.log(e);
        console.log(e.data); // 파일

//event로 data property를 가진 Blob Event를 받게됨 data를 받으면 사용자가 다운로드 받게할 수있음
    } 
    console.log(recorder); //state:inactive
    recorder.start();
    console.log(recorder); //state:recording
    setTimeout(()=>{
        recorder.stop();
    },10000);   //recorder.stop()이 되면 dataavailable에 접근가능 , blob데이터 받아 
}

 

콘솔 창 

MediaRecorder
https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder

MediaRecorder ondataavailable
https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/ondataavailable

 

handlestop을 누르면 

recorder.stop()하게 하고지만 hanldeStart에 recoder를 상수 변수로 만들었음 

따라서 let recorder로 외부에 변수지정 

 

const handleStart= () => {
    startBtn.innerText ="Stop Recording";
    startBtn.removeEventListener("click",handleStart);
    startBtn.addEventListener("click", hanldeStop);
    recorder = new MediaRecorder(stream,{mimeType:"video/webm"});
    recorder.ondataavailable = (e) =>{
        const videoFile = URL.createObjectURL(e.data); //브라우저 메모리에서만 가능한 URL을 만들어 줌 
        video.srcObject= null; //미리보기제거
        video.src = videoFile;
        video.loop = true;
        video.play();
    } 
    recorder.start();
}

 

URL.createObjectURL() creates an URL that is only available on the browser memory.
Simply, a URL that is pointing to the file. 브라우저에서 생성한 url이고 브라우저에서만 파일에 접근 할 수있는 url

We get the data after getting ondataavailable.
We put the data in URL.createObjectURL().

 

localhost에 존재하는 파일이아니고 브라우저에 메모리에 있는 파일 접근하기위해서 해당 url 필요 

 

URL.createObjectURL()
https://developer.mozilla.org/ko/docs/Web/API/URL/createObjectURL

 

URL.createObjectURL() - Web API | MDN

URL.createObjectURL() 정적 메서드는 주어진 객체를 가리키는 URL을 DOMString으로 반환합니다.

developer.mozilla.org

 

------

녹화한거 다운로드하기

let videoFile//공유하기 위해 전역변수로 

 

const handleDownload =()=>{
    const a = document.createElement("a");
    a.href= videoFile;
    a.download ="MyRecording.webm"; //다운로드할 파일의 포맷 정해주기 
    document.body.appendChild(a);
    a.click();
    
}
const hanldeStop = () =>{
    startBtn.innerText = "Download Recording";
    startBtn.removeEventListener("click",hanldeStop);
    startBtn.addEventListener("click", handleDownload);
    recorder.stop();

}

-----

FFmpeg

webmpg  --> mp4, 비디오 썸네일 추출 

동영상 다운받아지긴했지만 길이가 없는 동영상임 
모든 파일이webmpg 이해할 수 없다 mp4로 변환하기 
FFmpeg 비디오 압축, 변경,오디오추출,자막추가등  c언어로만들어짐 wbmpg이용해 프론트에서 처리

ff를 사용할려면 백엔드에서 사용해야함 ,콘솔

webassembly은 프론트를엔드에서 빠른 코드를 실행 할 수 있도록 도와줌 

실행비용이큰 프로그램을 브라우저에서 실행 할 수 있음 

서버처리(비용)로 하지않고 우리의 사용자 처리능력으로 

 

우리가 사용 할 개념 ffmpeg + webassembly -> ffmpeg.wasm

비디오를 변환하기위해 사용자의 컴퓨터를 사용함 

유투브 --> 업로도 된비디오를 비싼 서버에서 변환

우리는 웹어셈블리로 사용자 컴퓨터의 처리능력을 사용 할 것임 서버x, 

그리고 웹 어셈블리로 ffmpeg 이용 할 것임 


npm install @ffmpeg/ffmpeg @ffmpeg/core

https://github.com/ffmpegwasm/ffmpeg.wasm
https://www.npmjs.com/package/@ffmpeg/ffmpeg

웹 어셈블리는 자바스크립트의 무덤일까?
https://www.youtube.com/watch?v=KjgDxBLv0bM

 

reocorder.js

import {createFFmpeg, fetchFile} from "@ffmpeg/ffmpeg";
 
javascript가 아닌 다른 프로그램을 사용자 컴퓨터에서 실행하는 것이기 때문에 await 사용해야 함 

 

 

const handleDownload =async()=>{
    const ffmpeg = createFFmpeg({log:true});
    await ffmpeg.load();
  //ffmpeg세상에  filesysntem, 파일을 생성해 줌 , 파일명, binary Data videoFile은 URL을 가르 킴 
    ffmpeg.FS("writeFile", "recording.webm", await fetchFile(videoFile));
             ffppeg 실행 , input, 위에서 생성한 파일, 60초프레임단위로, 가상 파일 시스템에 생길 파일 
    await ffmpeg.run("-i", "recording.webm", "-r", "60", "output.mp4"); 

'코딩 > Today I Learn' 카테고리의 다른 글

에러로깅  (0) 2022.01.11
01.05공부  (0) 2022.01.05
1/03 공부  (0) 2022.01.03
12.29수 공부  (0) 2021.12.29
12.28일 화 공부  (0) 2021.12.28