크롬에서 띄운 화면을 녹화하고, 마이크 음성 및 컴퓨터에서 재생되고 있는 소리까지 녹음한다.

 

처음에 해상도를 지정하지 않고 녹화했을 때 저장되는 용량이 너무 크면

 

비디오스트림을 생성할때 해상도를 설정해서 용량을 낮출 수 있다. 

(해당 코드에서는 640x480으로 아주 낮게 설정되어있음)
(video: { width: 640 , height: 480 } -> video: true 로 설정하면 녹화 화면 해상도에 맞게 녹화된다)

 

녹화종료 버튼을 누르고 다운로드를 누르면 로컬에 저장된다. 

 

비디오, 오디오 스트림을 각각 만들고 해당 스트림들을 연결해서 동작한다.

 

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 
window.onload = () => {
  const startBtn = document.getElementById('startBtn');
  const stopBtn = document.getElementById('stopBtn');
  const download = document.getElementById('download');
  
  let blobs;
  let blob; // 데이터
  let rec; // 스트림을 기반으로 동작하는 mediarecorder 객체
  let stream; // 통합
  let voiceStream; // 오디오스트림
  let desktopStream; // 비디오스트림
  
  const mergeAudioStreams = (desktopStream, voiceStream) => { // 비디오, 오디오스트림 연결
    const context = new AudioContext();
    const destination = context.createMediaStreamDestination();
    let hasDesktop = false;
    let hasVoice = false;
    if (desktopStream && desktopStream.getAudioTracks().length > 0) {
      const source1 = context.createMediaStreamSource(desktopStream);
      const desktopGain = context.createGain();
      desktopGain.gain.value = 0.7;
      source1.connect(desktopGain).connect(destination);
      hasDesktop = true;
    }
    
    if (voiceStream && voiceStream.getAudioTracks().length > 0) {
      const source2 = context.createMediaStreamSource(voiceStream);
      const voiceGain = context.createGain();
      voiceGain.gain.value = 0.7;
      source2.connect(voiceGain).connect(destination);
      hasVoice = true;
    }
      
    return (hasDesktop || hasVoice) ? destination.stream.getAudioTracks() : [];
  };
 
  startBtn.onclick = async () => { // 녹화 시작 버튼을 누른 경우
    
    desktopStream = await navigator.mediaDevices.getDisplayMedia({ video: { width: 640 , height: 480 }, audio: true }); // 비디오스트림 생성
    voiceStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true }); // 오디오스트림 생성
  
    const tracks = [
      ...desktopStream.getVideoTracks(), 
      ...mergeAudioStreams(desktopStream, voiceStream)
    ];
    
    stream = new MediaStream(tracks);
      
    blobs = [];
 
    rec = new MediaRecorder(stream, {mimeType: 'video/webm; codecs=vp9,opus'}); // mediaRecorder객체 생성
    rec.ondataavailable = (e) => blobs.push(e.data);
    rec.onstop = async () => {
      
      blob = new Blob(blobs, {type: 'video/webm'});
      let url = window.URL.createObjectURL(blob);
      download.href = url;
      download.download = 'test.webm';
      download.style.display = 'block';
    };
    startBtn.disabled = true// 시작 버튼 비활성화
    stopBtn.disabled = false// 종료 버튼 활성화
    rec.start(); // 녹화 시작
  };
 
  stopBtn.onclick = () => { // 종료 버튼을 누른 경우
    // 버튼 비활성화
    startBtn.disabled = true;
    stopBtn.disabled = true;
    
    rec.stop(); // 화면녹화 종료 및 녹화된 영상 다운로드
    
    desktopStream.getTracks().forEach(s=>s.stop())
    voiceStream.getTracks().forEach(s=>s.stop())
    desktopStream = null;
    voiceStream = null;
 
    startBtn.disabled = false// 시작 버튼 활성화
  };
};
cs

 

끝~

+ Recent posts