본문 바로가기
기타 web 개발 지식

[WEB] MediaDevices와 MediaStream을 통해 알아보는 웹 실시간 미디어 처리 방식

by spare8433 2025. 3. 31.

1. MediaDevices 란?

navigator.mediaDevices 를 통해 웹에서 카메라, 마이크, 화면 공유와 같은 미디어 입력 장치에 접근하여, 해당 장치에서 제공하는 미디어 스트림을 가져올 수 있습니다.



※ Navigator 객체는 웹 브라우저의 정보를 제공하는 인터페이스로 window.navigator 읽기 전용 속성으로 접근할 수 있습니다.





1.1 이벤트


■ devicechange

새로운 미디어 장치가 연결되거나 기존 장치가 제거될 때 발생하는 이벤트입니다. ondevicechange 속성으로도 사용할 수 있습니다.



// `addEventListener`를 사용하는 방식 (권장)
navigator.mediaDevices.addEventListener('devicechange', event => {
  console.log('미디어 장치 구성이 변경되었습니다');
  // 장치 목록 다시 가져오기 등의 작업 수행
});

// `ondevicechange` 속성을 사용하는 방식 (권장 x): `ondevicechange`는 이벤트 핸들러 한 개만 등록 가능
navigator.mediaDevices.ondevicechange = () => {
  console.log("미디어 장치 변경 감지!");
};




1.2 메서드


■ getUserMedia()

사용자에게 권한을 요청한 후, 사용자의 카메라, 마이크 등 미디어 입력 장치에 접근하여 MediaStream 을 가져옵니다.


navigator.mediaDevices.getUserMedia(constraints)
  .then(stream => {
    // 스트림 사용하기
  })
  .catch(error => {
    console.error("미디어 장치 접근 실패:", error);
  });




constraints 객체는 요청할 미디어 유형과 각각의 요구사항을 명시합니다:

// simple
const constraints = {
  audio: true,  // 기본 오디오 설정
  video: true   // 기본 비디오 설정
};

or 

// detail
const constraints = {
  audio: {
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true
  },
  video: {
    width: { ideal: 1280 },
    height: { ideal: 720 },
    facingMode: "user"  // 전면 카메라
  }
};




■ enumerateDevices()

시스템에서 사용 가능한 모든 미디어 입력 및 출력 장치의 목록을 가져옵니다.

navigator.mediaDevices.enumerateDevices()
  .then(devices => {
    devices.forEach(device => {
      console.log(`${device.kind}: ${device.label}, id = ${device.deviceId}`);
    });
  })
  .catch(error => {
    console.error("장치 열거 실패:", error);
  });




■ getDisplayMedia()

사용자의 화면 콘텐츠(전체 화면, 애플리케이션 창, 또는 특정 탭)를 캡처할 수 있는 스트림을 제공합니다.

navigator.mediaDevices.getDisplayMedia({ video: true })
  .then(stream => {
    // 화면 공유 스트림 사용하기
  })
  .catch(error => {
    console.error("화면 공유 실패:", error);
  });










2. MediaStream

MediaStream 은 WebRTC 및 웹 미디어 API에서 사용되는 객체로, 오디오 및 비디오 스트림을 다룰 때 사용됩니다. 브라우저에서 마이크, 카메라, 화면 공유 등의 미디어 데이터를 실시간으로 처리할 수 있게 하며, 단일 또는 여러 미디어 트랙을 포함할 수 있습니다. 각 트랙은 특정 유형의 미디어 소스(예: 카메라, 마이크, 화면 콘텐츠)를 나타냅니다.




2.1 생성 및 접근 방법


MediaDevices.getUserMedia()

카메라/마이크 접근



MediaDevices.getDisplayMedia()

화면 공유



Canvas.captureStream()

캔버스 콘텐츠 스트리밍

const canvas = document.querySelector('canvas');
const stream = canvas.captureStream(30); // 30fps



기존 트랙으로부터 새 스트림 생성

const newStream = new MediaStream([videoTrack, audioTrack]);



다른 스트림 복제

const clonedStream = originalStream.clone();




2.2 이벤트


■ addtrack

새 트랙이 스트림에 추가될 때 발생합니다.


stream.addEventListener('addtrack', event => {
  console.log('트랙이 추가됨:', event.track);
});




■ removetrack

트랙이 스트림에서 제거될 때 발생합니다.


stream.addEventListener('removetrack', event => {
  console.log('트랙이 제거됨:', event.track);
});




2.3 속성



■ active

스트림이 활성 상태인지 여부를 나타내는 boolean 값입니다. 하나 이상의 트랙이 활성 상태면 true입니다.

console.log(stream.active); // true 또는 false



■ id

스트림의 고유 식별자입니다.

console.log(stream.id); // 예: "123e4567-e89b-12d3-a456-426614174000"




2.4 메서드


■ addTrack()

스트림에 새로운 트랙을 추가합니다.


stream.addTrack(track); // track은 MediaStreamTrack 객체




■ removeTrack()

스트림에서 트랙을 제거합니다.


stream.removeTrack(track);




■ getAudioTracks()

스트림 내의 모든 오디오 트랙을 배열로 반환합니다.


const audioTracks = stream.getAudioTracks();




■ getVideoTracks()

스트림 내의 모든 비디오 트랙을 배열로 반환합니다.


const videoTracks = stream.getVideoTracks();




■ getTracks()

스트림의 모든 트랙(오디오와 비디오)을 배열로 반환합니다.


const allTracks = stream.getTracks();




■ getTrackById()

지정된 ID를 가진 트랙을 반환합니다.


const track = stream.getTrackById(trackId);




■ clone()

스트림의 복제본을 생성합니다. 모든 트랙도 복제됩니다.

const clonedStream = stream.clone();













3. MediaStreamTrack

MediaStream트랙(MediaStreamTrack) 객체의 집합으로, 각 트랙은 오디오나 비디오 같은 특정 미디어 유형의 소스를 나타냅니다.




3.1 주요 속성


  • kind: 트랙의 유형 ('audio' 또는 'video')
  • id: 트랙의 고유 식별자
  • label: 트랙의 설명(예: 카메라 또는 마이크 이름)
  • enabled: 트랙의 활성화/비활성화 상태
  • muted: 트랙이 현재 음소거 상태인지 여부
  • readyState: 트랙의 현재 상태 ('live' 또는 'ended')




3.2 주요 메서드


  • stop(): 트랙을 영구적으로 중지
  • clone(): 트랙의 복제본 생성
  • getCapabilities(): 트랙의 가능한 설정 범위 가져오기
  • getConstraints(): 현재 적용된 제약 조건 가져오기
  • getSettings(): 현재 적용된 설정 가져오기
  • applyConstraints(): 새로운 제약 조건 적용하기










4, MediaStream 레코딩

MediaRecorder API를 사용하여 MediaStream을 녹화할 수 있습니다:



function recordStream(stream) {
  const chunks = [];
  const recorder = new MediaRecorder(stream);

  recorder.ondataavailable = e => {
    if (e.data.size > 0) {
      chunks.push(e.data);
    }
  };

  recorder.onstop = () => {
    const blob = new Blob(chunks, { type: 'video/webm' });
    const url = URL.createObjectURL(blob);

    // 비디오 저장 링크 생성
    const a = document.createElement('a');
    a.href = url;
    a.download = 'recording.webm';
    a.textContent = '녹화 다운로드';
    document.body.appendChild(a);
  };

  // 녹화 시작 (5초 동안)
  recorder.start();
  setTimeout(() => recorder.stop(), 5000);
}










5. 브라우저 호환성

  • 대부분의 최신 브라우저(Chrome, Firefox, Safari, Edge)에서 지원됩니다.
  • Safari는 일부 제한된 기능을 가질 수 있습니다.
  • 모바일 브라우저에서는 기능과 성능에 차이가 있을 수 있습니다.
  • 보안을 위해 HTTPS 환경에서만 완전히 작동합니다(localhost 제외).










6. 보안 고려사항

  • MediaStream API는 카메라, 마이크 등의 민감한 장치에 접근하므로 사용자의 명시적 권한이 필요합니다.
  • 대부분의 브라우저는 사용자가 허용하지 않은 미디어 장치에 접근할 수 없도록 차단합니다.
  • 사용자가 허용한 후에도 브라우저 UI에 미디어 장치 사용 중임을 표시합니다.
  • 백그라운드 탭에서는 미디어 캡처가 제한될 수 있습니다.
  • 영상 처리 시 사용자 개인정보를 고려해야 합니다.










참고

Media Capture and Streams API (미디어 스트림) - MDN
MediaDevices - MDN
MediaStream Recording API - MDN
MediaRecorder - MDN