게스트(아동) 페이지에서 USB 헤드셋을 연결하면 setSinkId()로 오디오 출력이 헤드셋으로 강제 라우팅됩니다.
이 시점부터 macOS / Windows 시스템 볼륨 슬라이더를 조작해도 앱 내 오디오(핑퐁이 음성, 활동 영상)의 볼륨이 변하지 않습니다.
일반 재생과 setSinkId() 사용 시의 경로 차이입니다.
setSinkId()는 W3C Audio Output Devices API 스펙에 따라 HTMLMediaElement의
오디오 출력을 특정 deviceId로 직접 바인딩합니다.
이 경로는 OS의 기본 오디오 세션(macOS Core Audio, Windows WASAPI)이 노출하는
볼륨 컨트롤 레이어를 거치지 않습니다.
OS 시스템 볼륨 슬라이더는 "기본 출력 장치(default output device)"의 세션 볼륨을 조절합니다.
setSinkId()로 지정된 스트림은 OS 입장에서 별개의 장치 스트림이기 때문에
기본 출력 슬라이더의 제어 범위 밖에 있습니다.
navigator.mediaSession은 재생/정지/트랙 이동만 지원하며 볼륨 이벤트를 노출하지 않습니다.
게스트 입장 시 findPreferredDevice()로 USB 헤드셋을 자동 감지하고,
감지된 deviceId를 각 오디오 엘리먼트에 적용합니다.
OS 설정과 무관하게 핑퐁이 음성과 활동 영상을 확실히 헤드셋으로 출력하기 위한 목적입니다.
| 파일 | 라우팅 대상 |
|---|---|
| use-ai-session.ts | 핑퐁이 AI 음성 |
| meet-video.tsx | 활동 영상 오디오 |
| use-host-session-relay.ts | 호스트→게스트 relay 오디오 |
| use-host-media-manager.ts | 원격 비디오 오디오 |
| 볼륨 제어 방법 | setSinkId 미사용 | setSinkId 사용 후 |
|---|---|---|
| macOS 시스템 볼륨 슬라이더 | 동작 | 미동작 |
| Windows 시스템 볼륨 슬라이더 | 동작 | 미동작 |
| 헤드셋 하드웨어 볼륨 버튼 | 동작 | 동작 (장치 자체 제어) |
| HTMLMediaElement.volume 프로퍼티 | 동작 | 동작 — 유일한 SW 제어 수단 |
| navigator.mediaSession 볼륨 | 미지원 (API 없음) | 미지원 (API 없음) |
setSinkId()로 라우팅된 스트림의 볼륨을 조절하는 유일한 SW 수단은
HTMLMediaElement.volume 프로퍼티 직접 조작입니다.
따라서 앱 내 볼륨 슬라이더 제공이 필수이며, 이것이 커밋 42a98a9e의 배경입니다.
// setSinkId() 라우팅 후 볼륨 제어
audioElement.setSinkId(deviceId);
audioElement.volume = 0.8; // 0.0 ~ 1.0, 이 방법만 유효
헤드셋 하드웨어 볼륨 버튼이 있는 경우 동작하지만 모든 기기에 해당하지 않으므로, 앱 내 슬라이더를 함께 제공하는 것이 정석입니다.