얼마 전 오디오 코스웨어를 개발하는 프로젝트였는데, 기본적으로 문서, 사진, 기타 리소스를 가져온 후 페이지가 PPT 같은 레이아웃이 되고, 사진을 선택하면 오디오를 삽입할 수 있는 두 가지 유형이 있습니다. 그리고 글로벌 편집 모델. 오디오를 가져오는 방법에는 두 가지가 있습니다. 하나는 리소스 라이브러리에서 가져오는 것이고, 다른 하나는 녹음을 언급하는 것입니다.
솔직히 말해서 처음에는 HTML5의 Audio API를 접해본 적이 없었고, 인수하기 전에는 코드를 기반으로 최적화를 해야 했습니다. 물론, 여기에는 많은 함정이 있습니다. 이번에는 이러한 함정에 대한 제 느낌에 대해서도 이야기하겠습니다. (일부 기본 객체의 초기화 및 획득은 이 내용이 이번 주제가 아니기 때문에 생략하겠습니다. 관심 있는 학생들은 MDN을 검색해 보세요. 자체적으로 문서화):
녹음을 시작하기 전에 먼저 현재 장치가 Audio API를 지원하는지 확인해야 합니다. 이전 메소드 navigator.getUserMedia는 navigator.mediaDevices.getUserMedia로 대체되었습니다. 일반적으로 대부분의 최신 브라우저는 navigator.mediaDevices.getUserMedia의 사용을 지원합니다. 물론 MDN은 호환성 정보도 제공합니다.
const promisifiedOldGUM = function(constraints) { // 먼저 getUserMedia를 가져옵니다. const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || // 일부 브라우저에서는 이를 구현하지 않습니다. - 거부된 약속을 반환합니다. 오류가 발생함 // 일관된 인터페이스를 유지하기 위해 if (!getUserMedia) { return Promise.reject( new Error('getUserMedia는 이 브라우저에서 구현되지 않았습니다.') ) } // 그렇지 않으면 Promise로 이전 navigator.getUserMedia에 대한 호출을 래핑합니다. return new Promise(function(resolve, Reject) { getUserMedia.call (navigator, 제약 조건, 해결, 거부); });}; // 이전 브라우저에서는 mediaDevices가 전혀 구현되지 않을 수 있으므로 먼저 빈 객체를 설정합니다. (navigator.mediaDevices === 정의되지 않음) { navigator.mediaDevices = {};} // 일부 브라우저는 mediaDevices를 부분적으로 구현합니다. // 기존 속성을 덮어쓰므로 getUserMedia를 사용하여 객체를 할당할 수 없습니다.// 여기서는 getUserMedia 속성이 누락된 경우 추가합니다.if (navigator.mediaDevices.getUserMedia === 정의되지 않음) { navigator.mediaDevices.getUserMedia = promisifiedOldGUM;}
이 방법은 비동기식이므로 호환되지 않는 장치에 대해 친숙한 프롬프트를 제공할 수 있습니다.
navigator.mediaDevices.getUserMedia(constraints).then( function(mediaStream) { // 성공 }, function(error) { // 실패 const { name } = error; let errorMessage; switch (name) { // 사용자가 사례를 거부함 ' NotAllowedError': case 'PermissionDeniedError': errorMessage = '사용자가 웹페이지에서 녹음 장치를 호출하는 것을 금지했습니다.' // 녹음 장치가 연결되지 않았습니다. case 'NotFoundError': case; 'DevicesNotFoundError': errorMessage = '녹음 장치를 찾을 수 없습니다.'; // 기타 오류 사례 'NotSupportedError': errorMessage = '녹음 기능이 지원되지 않습니다.' break; default: errorMessage = '녹음 호출 오류'; 로그(오류); } 오류 메시지 반환 });
모든 것이 잘 진행되면 다음 단계로 넘어갈 수 있습니다.
(맥락을 얻는 방법은 이번에는 초점이 아니기 때문에 여기서는 생략합니다)
녹음 시작, 녹음 일시 정지여기에는 특별한 점이 있는데, 현재 녹화가 진행 중인지 확인하기 위해 중간 변수를 추가해야 한다는 점이다. 파이어폭스 브라우저에서는 문제가 발견됐는데, 녹화 과정이 정상적으로 진행됐으나 일시정지 버튼을 눌렀을 때, 당시에는 연결 끊기 방식을 사용했던 것으로 확인됐습니다. 이 방법은 불가능합니다. 모든 연결을 끊어야 합니다. 나중에 녹음이 현재 진행 중인지 확인하려면 중간 변수 this.isRecording을 추가해야 한다는 사실을 발견했습니다. 시작을 클릭하면 true로 설정하고 일시 정지하면 false로 설정합니다.
녹음을 시작하면 audioprocess에서 녹음 듣기 이벤트가 발생합니다. true가 반환되면 스트림이 기록됩니다. 그러므로 this.isRecording으로 판단하고 false일 경우 바로 return한다.
// 일부 초기화 const audioContext = new AudioContext(); const sourceNode = audioContext.createMediaStreamSource(mediaStream); const scriptNode = audioContext.createScriptProcessor( BUFFER_SIZE, INPUT_CHANNELS_NUM, OUPUT_CHANNELS_NUM);sourceNode.connect(this.scriptNode);scriptNode.connect(this.audioContext.destination); // 녹음 프로세스 모니터링 scriptNode.onaudioprocess = event => { if (!this.isRecording) return; 정기 녹화 this.buffers.push(event.inputBuffer.getChannelData(0)) // 현재 채널의 데이터를 가져와서 배열에 씁니다};
물론 여기에는 더 이상 사용할 수 없다는 함정이 있을 것입니다. 실제로는 실제 일시 중지가 아니지만 스트림이 기록되지 않기 때문에 현재 녹음 기간을 얻는 방법이 제공됩니다. 따라서 현재 녹음의 지속 시간도 가져와야 하며, 이는 공식을 통해 얻어야 합니다.
const getDuration = () => { return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096은 스트림의 길이, SampleRate는 샘플링 속도입니다.}
이렇게 하면 올바른 녹음 기간을 얻을 수 있습니다.
녹음 종료녹음을 끝내려면 먼저 일시 중지한 다음 필요한 경우 청취 또는 기타 작업을 수행한 다음 스토리지 스트림의 배열 길이를 0으로 설정합니다.
빈도 얻기getVoiceSize = analyzer => { const dataArray = new Uint8Array(analyser.주파수BinCount); analyzer.getByteFrequencyData(dataArray); const data = dataArray.slice(100, 1000); const sum = data.reduce((a, b) => a + b) 반환 합계;};
자세한 내용은 https://developer.mozilla.org/zh-CN/docs/Web/API/AnalyserNode/주파수BinCount를 참조하세요.
다른
이번에 겪은 문제는 대부분 호환성 문제여서 함정에 많이 빠졌는데, 특히 모바일 쪽에서는 처음에는 녹화 시간을 잘못 적어서 바로 멈추는 문제가 있었습니다. 물론, 가장 중요한 것은 이러한 종류의 기본 API 문서가 MDN을 직접 보면 간단하고 대략적으로 얻을 수 있다는 점을 모든 사람에게 상기시키는 것입니다.
위 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.