생일 축하 메시지를 링크로 보내고 싶었다. 받는 사람이 케이크 위 촛불 다섯 개를 휴대폰에 후 불어서 끄면 폭죽이 터지는 페이지다.
바람을 어떻게 감지하나#
Web Audio의 AnalyserNode로 마이크 입력의 소리 크기(RMS)를 계속 잰다.
- 접속 후 처음 0.7초 동안의 주변 소음으로 기준값을 잡는다.
max(0.06, 기준×4)를 넘는 소리가 0.2초 이상 이어지면 “분다”고 판단한다.- 촛불을 앞에서부터 0.17초 간격으로 하나씩 끈다.
에코 제거, 소음 억제, 자동 이득 조절은 모두 끈다. 켜 두면 입김처럼 낮고 거센 소리를 브라우저가 소음으로 지워 버린다.
폭죽은 캔버스에 입자(중력, 회전, 페이드)로 직접 그렸다.
한계#
소리 크기만 보기 때문에 큰 말소리에도 꺼질 수 있다. 입김은 저음이 강하다는 특징이 있어서 주파수 분포로 걸러 내면 더 나아질 것 같고, 실제 기기에서 감도를 조정해 볼 계획이다.
알게 된 것들#
마이크는 https에서만 켜진다. 처음에는 Claude 아티팩트 화면으로 만들려 했는데, 아티팩트는 마이크와 카메라를 막는다. 마이크가 필요한 페이지는 Firebase Hosting 같은 https 호스팅에 올려야 한다.
카카오톡 인앱 브라우저는 마이크를 막는다. 링크를 카톡으로 보내면 받는 사람이 인앱 브라우저로 열기 때문에, 접속 시 기본 브라우저로 넘기는 한 줄을 넣었다.
if (/KAKAOTALK/i.test(navigator.userAgent)) {
location.href = 'kakaotalk://web/openExternal?url=' + encodeURIComponent(location.href)
}js아이폰과 일부 기기는 화면을 한 번 만져야 소리가 시작된다. 브라우저가 자동 재생을 막기 때문에 AudioContext.resume()을 터치 시점에 호출해야 한다. 마이크 허용을 거부하는 사람을 위해, 촛불을 눌러서도 끌 수 있게 했다.