โปรเจ็กต์เมื่อก่อนคือการพัฒนาบทเรียนเกี่ยวกับเสียง โดยพื้นฐานแล้ว หลังจากนำเข้าเอกสาร รูปภาพ และทรัพยากรอื่นๆ แล้ว หน้าดังกล่าวจะกลายเป็นเลย์เอาต์ที่คล้ายกับ PPT จากนั้นการเลือกรูปภาพสามารถแทรกเสียงได้ การแก้ไขหน้าเดียวมีอยู่สองประเภท และการแก้ไขแบบสากล มีสองวิธีในการนำเข้าเสียง วิธีหนึ่งคือการนำเข้าจากไลบรารีทรัพยากร และอีกวิธีหนึ่งคือการพูดถึงการบันทึก
พูดตามตรง ฉันไม่เคยได้สัมผัสกับ Audio API ของ HTML5 เลยตั้งแต่แรก และเราต้องปรับให้เหมาะสมตามโค้ดก่อนที่เราจะรับช่วงต่อ แน่นอนว่ายังมีข้อผิดพลาดอยู่หลายประการ คราวนี้ฉันจะพูดถึงความรู้สึกของฉันเกี่ยวกับข้อผิดพลาดเหล่านี้ด้วย (การเริ่มต้นและการได้มาซึ่งวัตถุพื้นฐานบางอย่างจะถูกละเว้นเนื่องจากเนื้อหาเหล่านี้ไม่ได้เป็นจุดสนใจของเวลานี้ นักเรียนที่สนใจสามารถค้นหา 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 is not allowance in this browser') ); } // มิฉะนั้น ให้ตัดการเรียกไปยัง navigator.getUserMedia เก่าด้วย Promise return new Promise(function(resolve, reject) { getUserMedia.call (เนวิเกเตอร์, ข้อจำกัด, แก้ไข, ปฏิเสธ); });}; // เบราว์เซอร์รุ่นเก่าอาจไม่ใช้งาน mediaDevices เลย ดังนั้นเราจึงตั้งค่าออบเจ็กต์ว่างก่อน (navigator.mediaDevices === undefinition) { navigator.mediaDevices = {};} // เบราว์เซอร์บางตัวใช้งาน mediaDevices บางส่วน เราไม่สามารถกำหนดอ็อบเจ็กต์ได้ // ด้วย getUserMedia เพราะมันจะเขียนทับคุณสมบัติที่มีอยู่ // ที่นี่ เรา จะเพิ่มคุณสมบัติ getUserMedia ถ้ามันหายไป if (navigator.mediaDevices.getUserMedia === undefinition) { navigator.mediaDevices.getUserMedia = สัญญาเก่าGUM;}
เนื่องจากวิธีนี้เป็นแบบอะซิงโครนัส เราจึงสามารถจัดเตรียมข้อความแจ้งที่เป็นมิตรสำหรับอุปกรณ์ที่เข้ากันไม่ได้
navigator.mediaDevices.getUserMedia(constraints).then( function(mediaStream) { // Success }, function(error) { // Failure const { name } = error; Let errorMessage; switch (ชื่อ) { // ผู้ใช้ปฏิเสธ case ' NotAllowedError': case 'PermissionDeniedError': errorMessage = 'ผู้ใช้ห้ามไม่ให้เว็บเพจเรียกอุปกรณ์บันทึก'; // อุปกรณ์บันทึกไม่ได้เชื่อมต่อ case 'NotFoundError': case 'DevicesNotFoundError': errorMessage = 'ไม่พบอุปกรณ์บันทึก'; // กรณีข้อผิดพลาดอื่น ๆ 'NotSupportedError': errorMessage = 'ไม่รองรับฟังก์ชันการบันทึก'; บันทึก (ข้อผิดพลาด); } กลับข้อผิดพลาด });
หากทุกอย่างเป็นไปด้วยดี เราก็สามารถไปยังขั้นตอนต่อไปได้
(วิธีการรับบริบทถูกละเว้นที่นี่ เนื่องจากไม่ใช่จุดเน้นในครั้งนี้)
เริ่มการบันทึก หยุดการบันทึกชั่วคราวมีจุดพิเศษตรงนี้ นั่นคือ จำเป็นต้องเพิ่มตัวแปรระดับกลางเพื่อระบุว่ากำลังทำการบันทึกอยู่หรือไม่ เนื่องจากในเบราว์เซอร์ Firefox เราพบปัญหา กระบวนการบันทึกเป็นเรื่องปกติ แต่เมื่อเราคลิกเพื่อหยุดชั่วคราว เราพบว่าไม่สามารถหยุดชั่วคราวได้ เราใช้วิธีตัดการเชื่อมต่อในขณะนั้น วิธีนี้ไม่สามารถทำได้ วิธีนี้จำเป็นต้องยกเลิกการเชื่อมต่อทั้งหมด ต่อมาฉันค้นพบว่าควรเพิ่มตัวแปรระดับกลาง this.isRecording เพื่อตรวจสอบว่ากำลังมีการบันทึกอยู่หรือไม่ เมื่อคลิกเริ่ม ให้ตั้งค่าเป็นจริง และเมื่อหยุดชั่วคราว ให้ตั้งค่าเป็นเท็จ
เมื่อเราเริ่มการบันทึก จะมีเหตุการณ์การฟังการบันทึกเกิดขึ้น หากคืนค่าเป็น true สตรีมจะถูกเขียน หากคืนค่าเป็น false ก็จะไม่ถูกเขียน ดังนั้น ให้ตัดสิน this.isRecording และหากเป็นเท็จ ให้ส่งคืนโดยตรง
// การเริ่มต้นบางอย่าง 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.frequencyBinCount); analyser.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/frequencyBinCount
อื่น
ปัญหาส่วนใหญ่ที่ฉันพบในครั้งนี้คือปัญหาด้านความเข้ากันได้ ดังนั้นฉันจึงพบข้อผิดพลาดมากมาย โดยเฉพาะในด้านอุปกรณ์เคลื่อนที่ ในตอนแรก มีปัญหาที่เขียนระยะเวลาการบันทึกไม่ถูกต้อง ทำให้เกิดการค้างโดยตรง ประสบการณ์นี้ยังช่วยชดเชยช่องว่างบางอย่างใน HTML5 API อีกด้วย แน่นอนว่าสิ่งที่สำคัญที่สุดคือการเตือนทุกคนว่าเอกสาร API ดั้งเดิมประเภทนี้ได้มาอย่างง่ายดายและหยาบคายจากการดู MDN โดยตรง!
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network