整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          如何使用 MediaStream API 錄制音頻

          和安全管理服務(wù)專家新鈦云服 方章和翻譯

          Media Capture and Streams API(又名 MediaStream API)允許您從用戶的麥克風(fēng)錄制音頻,然后將錄制的音頻或媒體元素作為音軌獲取。然后,您可以在錄制后直接播放這些曲目,也可以將錄制的媒體上傳到您的服務(wù)器。

          在本教程中,我們將創(chuàng)建一個網(wǎng)站,該網(wǎng)站將使用 Media Streams API 來允許用戶錄制某些內(nèi)容,然后將錄制的音頻上傳到服務(wù)器進(jìn)行保存。用戶還可以查看和播放所有上傳的錄音。

          您可以在此 https://github.com/sitepoint-editors/mediastream-tutorial 倉庫中找到本教程的完整代碼。


          準(zhǔn)備一個服務(wù)器


          我們將首先基于Node.js創(chuàng)建一個Express服務(wù),如果您的機(jī)器上沒有Node.js,請務(wù)必下載并安裝它。


          創(chuàng)建一個目錄

          建一個項(xiàng)目目錄,然后切換到該目錄下:

          mkdir recording-tutorialcd recording-tutorial


          初始化項(xiàng)目

          然后,用npm初始化項(xiàng)目:

          npm init -y   //選項(xiàng) -y 使用默認(rèn)值創(chuàng)建 package.json


          安裝需要依賴的包

          接下來,我們將為我們正在創(chuàng)建的服務(wù)器安裝 Express 并借用nodemon讓其支持熱重啟:

          npm i express nodemon


          創(chuàng)建一個express服務(wù)

          我們現(xiàn)在可以從創(chuàng)建一個簡單的服務(wù)器開始。在根目錄中創(chuàng)建index.js并填寫以下代碼:

          const path= require('path');
          const express = require('express');
          const app = express();
          const port = process.env.PORT || 3000;
          
          app.use(express.static('public/assets'));
          
          app.listen(port, () => {
           console.log(`App listening at http://localhost:${port}`);
          });

          創(chuàng)建一個服務(wù)器,當(dāng)前環(huán)境中如果沒有啟用了3000端口的話它將在3000端口上運(yùn)行,并且提供了一個靜態(tài)資源目錄public/assets--我們將很快創(chuàng)建它來保存JavaScript和CSS文件以及圖片。


          添加腳本

          最后,在package.json中的scripts下添加一個啟動腳本:

          "scripts": {
           "start": "nodemon index.js"
          },


          啟動web服務(wù)

          讓我們來測試下創(chuàng)建的服務(wù)器,運(yùn)行以下命令啟動服務(wù)器:

          npm start

          服務(wù)器應(yīng)從3000端口監(jiān)聽,你可以嘗試訪問localhost:3000,但你會看到一個消息說:"Cannot GET /",這是因?yàn)槲覀儧]有定義任何路由。


          創(chuàng)建一個錄音的頁面

          接下來,我們將創(chuàng)建一個主頁面,用戶將使用此頁面記錄、查看和播放錄音

          在public目錄中創(chuàng)建包含以下內(nèi)容的index.html文件:

          <!DOCTYPE html>
          <html lang="en"><head> <meta charset="UTF-8">
           <meta http-equiv="X-UA-Compatible" content="IE=edge">
           <meta name="viewport" content="width=device-width, initial-scale=1.0">
           <title>Record</title>
           <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"rel="stylesheet"
             integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
           <link href="/css/index.css" rel="stylesheet" />
          </head><body class="pt-5">
           <div class="container">
             <h1 class="text-center">Record Your Voice</h1>
             <div class="record-button-container text-center mt-5">
               <buttonclass="bg-transparent border btn record-button rounded-circle shadow-sm text-center" id="recordButton">
                 <img src="/images/microphone.png" alt="Record" class="img-fluid" />
               </button>
             </div>
           </div></body>
          </html>

          這個頁面使用Bootstrap 5進(jìn)行樣式設(shè)置。目前,該頁面只顯示了一個用戶可以用來錄制的按鈕。

          請注意,我們正在使用圖標(biāo)為麥克風(fēng)設(shè)計一個按鈕, 你可以在Iconscout上下載圖標(biāo),也可以使用GitHub存儲庫中的修改。

          下載圖標(biāo)并將其放在public/assets/images中,名稱為microphone.png。


          添加樣式

          我們要引用樣式表index.css,所以創(chuàng)建一個public/assets/css/index.css文件,內(nèi)容如下。

          .record-button {
           height: 8em;
           width: 8em;
           border-color: #f3f3f3!important;
          }
          
          .record-button:hover {
           box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important;
          }


          創(chuàng)建路由

          最后,我們只需要在index.js中添加新的路由。在app.listen之前添加以下內(nèi)容:

          app.get('/', (req, res) => {
           res.sendFile(path.join(__dirname, 'public/index.html'));
          });


          如果服務(wù)器還沒有運(yùn)行,使用npm start啟動服務(wù)器,然后在瀏覽器中訪問localhost:3000,您將看到一個記錄按鈕。

          目前,這個按鈕沒有任何作用。我們需要綁定一個觸發(fā)錄音的單擊事件。

          創(chuàng)建文件public/assets/js/record.js并填入以下內(nèi)容:

          //initialize elements we'll useconst recordButton = document.getElementById('recordButton');
          constrecordButtonImage = recordButton.firstElementChild;
          
          letchunks = []; //will be used later to record audioletmediaRecorder = null; //will be used later to record audiolet audioBlob = null; //the blob that will hold the recorded audio


          然后初始化一個record的函數(shù), 綁定該函數(shù)到點(diǎn)擊事件:

          function record() {
           //TODO start recording
          }
          
          recordButton.addEventListener('click', record);

          我們還將此功能作為事件監(jiān)聽器附加到記錄按鈕。


          錄音功能

          為了開始錄制,我們需要使用mediaDevices.getUserMedia()方法。

          這個方法允許我們獲得一個流,只有在用戶同意的情況下,才能錄制用戶的音頻和/或視頻。getUserMedia方法允許我們訪問本地輸入設(shè)備。

          getUserMedia接受一個MediaStreamConstraints對象作為參數(shù),它包括一組約束條件,指定我們從getUserMedia獲得的流中的預(yù)期媒體類型。這些約束可以是帶有布爾值的音頻和視頻。

          如果值為false,意味著用戶拒絕了這個訪問設(shè)備的行為。

          getUserMedia返回一個承諾。如果用戶允許網(wǎng)站進(jìn)行記錄,程序會收到一個MediaStream對象,我們可以用它來對用戶的視頻或音頻流進(jìn)行媒體截取。


          媒體采集和流

          為了使用MediaStream API對象來捕獲媒體軌道,我們需要使用MediaRecorder接口。我們需要創(chuàng)建一個該接口的新對象,它在構(gòu)造函數(shù)中接受MediaStream對象,并允許我們通過它的方法輕松地控制錄音。

          在記錄函數(shù)中,添加以下內(nèi)容:

          //check if browser supports getUserMedia
          if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
           alert('Your browser does not support recording!');
           return;
          }
          
          // browser supports getUserMedia
          // change image in button
          recordButtonImage.src = `/images/${mediaRecorder && mediaRecorder.state === 'recording' ? 'microphone' : 'stop'}.png`;
          if (!mediaRecorder) {
           // start recording
           navigator.mediaDevices.getUserMedia({
             audio: true,
          })
            .then((stream) => {
               mediaRecorder = new MediaRecorder(stream);
               mediaRecorder.start();
               mediaRecorder.ondataavailable = mediaRecorderDataAvailable;
               mediaRecorder.onstop = mediaRecorderStop;
            })
            .catch((err) => {
               alert(`The following error occurred: ${err}`);
               // change image in button
               recordButtonImage.src = '/images/microphone.png';
            });
          } else {
           // stop recording
           mediaRecorder.stop();
          }


          瀏覽器支持

          我們首先要檢查navigator.mediaDevices和navigator.mediaDevices.getUserMedia是否被定義,因?yàn)橛行g覽器如Internet Explorer、Android上的Chrome或其他瀏覽器并不支持它。

          此外,使用getUserMedia需要安全的網(wǎng)站,這意味著要么使用HTTPS、file://或從localhost加載的頁面。所以,如果頁面沒有安全加載,mediaDevices和getUserMedia將無法定義。


          開始錄音

          如果條件是false(即mediaDevices和getUserMedia都支持),我們首先將錄音按鈕的圖片改為stop.png,你可以從Iconscout或GitHub倉庫下載,并將其放在public/assets/images中。

          然后,我們要檢查mediaRecorder--我們在文件開頭定義的--是否為空。

          如果它是空的,就意味著沒有正在進(jìn)行的錄制。所以,我們使用getUserMedia獲得一個MediaStream實(shí)例來開始錄制。

          我們傳遞給它一個只有鍵值為audio和值為true的對象,因?yàn)槲覀冎皇窃阡浿埔纛l。

          這就是瀏覽器提示用戶允許網(wǎng)站訪問麥克風(fēng)的地方。如果用戶允許,程序中的代碼將被執(zhí)行。

          mediaRecorder = new MediaRecorder(stream);
          mediaRecorder.start();
          mediaRecorder.ondataavailable = mediaRecorderDataAvailable;
          mediaRecorder.onstop = mediaRecorderStop;


          這里我們要創(chuàng)建一個新的MediaRecorder,把它分配給我們在文件開頭定義的mediaRecorder。

          我們把從getUserMedia收到的數(shù)據(jù)流傳遞給構(gòu)造函數(shù)。然后,我們使用mediaRecorder.start()開始錄制。

          最后,我們將事件處理程序(我們將很快創(chuàng)建)與兩個事件,dataavailable和stop綁定。

          我們還添加了一個catch處理程序,以防用戶不允許網(wǎng)站訪問麥克風(fēng)或可能拋出的任何其他異常。



          停止錄制

          如果mediaRecorder不是空的,這一切都會發(fā)生。如果它是空的,這意味著有一個正在進(jìn)行的錄音,而用戶正在結(jié)束它。所以,我們使用mediaRecorder.stop()方法來停止錄音。

          } else {
           //stop recording
           mediaRecorder.stop();
          }


          處理媒體錄制事件

          到目前為止,我們的代碼在用戶單擊記錄按鈕時開始和停止記錄。接下來,我們將為可用數(shù)據(jù)添加事件處理程序并停止。


          當(dāng)數(shù)據(jù)可用

          dataavailable事件要么在完成完整的記錄時被觸發(fā),要么基于傳遞給mediaRecorder.start()的可選參數(shù)timeslice來指示該事件應(yīng)該被觸發(fā)的毫秒數(shù)。傳遞timeslice可以對錄音進(jìn)行切片,并以塊狀形式獲取。

          創(chuàng)建mediaRecorderDataAvailable函數(shù),該函數(shù)將處理dataavailable事件,只需將收到的BlobEvent參數(shù)中的Blob音軌添加到我們在文件開頭定義的chunks數(shù)組中。

          function mediaRecorderDataAvailable(e) {
           chunks.push(e.data);
          }

          chunks是用來保存用戶錄音的音軌數(shù)組。


          停止

          在我們創(chuàng)建mediaRecorderStop(它將處理停止事件)之前,讓我們首先添加HTML元素容器,它將容納錄制的音頻,并有保存和丟棄按鈕。

          在public/index.html中的</body>標(biāo)簽結(jié)束前添加以下內(nèi)容。

          <div class="recorded-audio-container mt-5 d-none flex-column justify-content-center align-items-center"
           id="recordedAudioContainer">
           <div class="actions mt-3">
             <button class="btn btn-success rounded-pill" id="saveButton">Save</button>
             <button class="btn btn-danger rounded-pill"id="discardButton">Discard</button>
           </div>
          </div>


          然后,在public/assets/js/record.js的開頭,添加一個變量,它將是#recordedAudioContainer元素的一個Node實(shí)例。

          const recordedAudioContainer = document.getElementById('recordedAudioContainer');


          我們現(xiàn)在可以實(shí)現(xiàn)mediaRecorderStop。這個函數(shù)首先會刪除之前錄制的、沒有保存的任何音頻元素,創(chuàng)建一個新的音頻媒體元素,將src設(shè)置為錄制流的Blob,并顯示容器。

          function mediaRecorderStop () {
           //check if there are any previous recordings and remove them
           if (recordedAudioContainer.firstElementChild.tagName === 'AUDIO') {
             recordedAudioContainer.firstElementChild.remove();
          }
           //create a new audio element that will hold the recorded audio
           const audioElm = document.createElement('audio');
           audioElm.setAttribute('controls', ''); //add controls
           //create the Blob from the chunks
           audioBlob = new Blob(chunks, { type: 'audio/mp3' });
           const audioURL = window.URL.createObjectURL(audioBlob);
           audioElm.src = audioURL;
           //show audio
           recordedAudioContainer.insertBefore(audioElm, recordedAudioContainer.firstElementChild);
           recordedAudioContainer.classList.add('d-flex');
           recordedAudioContainer.classList.remove('d-none');
           //reset to default
           mediaRecorder = null;
           chunks = [];
          }


          最后,我們要把mediaRecorder和chunks重置為初始值,以處理接下來的錄音。有了這段代碼,我們的網(wǎng)站應(yīng)該能夠錄制音頻,當(dāng)用戶停止時,它允許他們播放錄制的音頻。

          我們需要做的最后一件事是在index.html中鏈接到record.js。在body末尾添加該腳本。

          <script src="/js/record.js"></script>


          測試

          現(xiàn)在讓我們來看看,在你的瀏覽器中訪問localhost:3000,點(diǎn)擊錄音按鈕會詢問是否允許網(wǎng)站使用麥克風(fēng)

          請確保你在本地主機(jī)或HTTPS服務(wù)器上加載網(wǎng)站,即使你使用的是支持的瀏覽器。在其他條件下,MediaDevices和getUserMedia是不可用的。

          點(diǎn)擊 "允許"。然后,麥克風(fēng)的圖像將變?yōu)橥V沟膱D像。同時,根據(jù)你的瀏覽器,你應(yīng)該在地址欄看到一個錄音圖標(biāo)。這表明麥克風(fēng)目前已被網(wǎng)站訪問。

          試著錄制幾秒鐘。然后點(diǎn)擊停止按鈕。按鈕的圖像將變回麥克風(fēng)的圖像,音頻播放器將顯示兩個按鈕--保存和取消。

          接下來,我們將實(shí)現(xiàn)保存和取消按鈕的點(diǎn)擊事件。保存按鈕應(yīng)該將音頻上傳到服務(wù)器,而取消按鈕應(yīng)該將其刪除。


          取消按鈕功能實(shí)現(xiàn)

          我們首先要實(shí)現(xiàn)取消按鈕的事件處理程序。點(diǎn)擊這個按鈕應(yīng)該首先向用戶顯示一個提示,讓他們確認(rèn)是否要放棄錄音。然后,如果用戶確認(rèn)了,它將移除音頻播放器并隱藏按鈕。

          在public/assets/js/record.js的開頭添加將容納取消按鈕的變量。

          const discardAudioButton = document.getElementById('discardButton');
          function discardRecording () {
           //show the user the prompt to confirm they want to discard
           if (confirm('Are you sure you want to discard the recording?')) {
             //discard audio just recorded
             resetRecording();
          }
          }
          
          functionresetRecording () {
           if (recordedAudioContainer.firstElementChild.tagName === 'AUDIO') {
             //remove the audio
             recordedAudioContainer.firstElementChild.remove();
             //hide recordedAudioContainer
             recordedAudioContainer.classList.add('d-none');
             recordedAudioContainer.classList.remove('d-flex');
          }
           //reset audioBlob for the next recording
           audioBlob = null;
          }
          
          //add the event listener to the button
          discardAudioButton.addEventListener('click', discardRecording);

          您現(xiàn)在測試一下,然后單擊取消按鈕,音頻播放器將被刪除,按鈕會隱藏。


          上傳到服務(wù)器

          現(xiàn)在,我們將實(shí)現(xiàn) "保存 "按鈕的點(diǎn)擊處理程序。當(dāng)用戶點(diǎn)擊保存按鈕時,該處理程序?qū)⑹褂肍etch API將audioBlob上傳至服務(wù)器。

          如果你對Fetch API不熟悉,可以在我們的 "Fetch API介紹 "教程中了解更多。


          讓我們先在項(xiàng)目根目錄下創(chuàng)建一個uploads目錄:

          mkdir uploads


          然后,在record.js的開頭,添加一個變量來保存Save按鈕元素:

          constsaveAudioButton = document.getElementById('saveButton');
          functionsaveRecording () {
           //the form data that will hold the Blob to upload constformData = new FormData();
           //add the Blob to formData
           formData.append('audio', audioBlob, 'recording.mp3');
           //send the request to the endpoint
           fetch('/record', {
             method: 'POST',
             body: formData
          })
          .then((response) => response.json())
          .then(() => {
             alert("Your recording is saved");
             //reset for next recording
             resetRecording();
             //TODO fetch recordings
          })
          .catch((err) => {
             console.error(err);
             alert("An error occurred, please try again later");
             //reset for next recording
             resetRecording();
          })
          }
          
          //add the event handler to the click event
          saveAudioButton.addEventListener('click', saveRecording);

          注意,一旦錄音被上傳,我們就用resetRecording來重置下一個錄音的音頻。稍后,我們將獲取所有的錄音,向用戶展示這些錄音。


          創(chuàng)建api

          我們現(xiàn)在需要實(shí)現(xiàn)上傳API。這個API將把音頻上傳到uploads目錄中。

          為了在Express中輕松處理文件上傳,我們將使用Multer庫。Multer提供了一個處理文件上傳的中間件。

          運(yùn)行以下程序來安裝它:

          npm i multer
          // 在Index.js中添加以下內(nèi)容const fs = require('fs');
          constmulter = require('multer');
          
          const storage = multer.diskStorage({
           destination(req, file, cb) {
             cb(null, 'uploads/');
          },
           filename(req, file, cb) {
             const fileNameArr = file.originalname.split('.');
             cb(null, `${Date.now()}.${fileNameArr[fileNameArr.length - 1]}`);
          },
          });
          const upload = multer({ storage });


          我們使用multer.diskStorage聲明了存儲,我們將其配置為在uploads目錄下存儲文件,并且我們將根據(jù)當(dāng)前的時間戳與擴(kuò)展名來保存文件。

          然后,我們聲明了upload,這將是上傳文件的中間件。

          接下來,我們要使uploads目錄中的文件可以公開訪問。所以,在app.listen前添加以下內(nèi)容。

          app.use(express.static('uploads'));


          最后,我們將創(chuàng)建上傳接口。這個接口將只是使用上傳中間件來上傳音頻并返回一個JSON響應(yīng)。

          app.post('/record', upload.single('audio'), (req, res) => res.json({ success: true }));


          上傳中間件將處理文件的上傳。我們只需要把我們要上傳的文件的字段名傳遞給upload.single。

          請注意,通常情況下,你需要對文件進(jìn)行驗(yàn)證,確保上傳的是正確的、預(yù)期的文件類型。為了簡單起見,我們在本教程中省略了這一點(diǎn)。


          測試上傳

          讓我們來測試一下。再次進(jìn)入訪問localhost:3000,錄制一些東西,然后點(diǎn)擊保存按鈕。

          請求上傳接口,文件將被上傳,并將向用戶顯示一個提示,通知他們錄音已被保存。

          你可以通過檢查你項(xiàng)目根部的uploads目錄來確認(rèn)音頻是否真的被上傳。你應(yīng)該在那里找到一個MP3音頻文件。


          展示上傳的音頻

          創(chuàng)建相關(guān)接口:

          我們要做的最后一件事是向用戶展示所有的錄音,以便他們可以播放。

          首先,我們要創(chuàng)建一個接口,用來獲取所有的文件。在index.js的app.listen前添加以下內(nèi)容。

          app.get('/recordings', (req, res) => {
           letfiles = fs.readdirSync(path.join(__dirname, 'uploads'));
           files = files.filter((file) => {
             // check that the files are audio files
             const fileNameArr = file.split('.');
             return fileNameArr[fileNameArr.length - 1] === 'mp3';
          }).map((file) => `/${file}`);
           return res.json({ success: true, files });
          });


          我們只是在讀取uploads目錄下的文件,過濾它們,只得到mp3文件,并在每個文件名后加上一個/。最后,我們將返回一個包含文件的JSON對象。

          在html中展示:

          <h2 class="mt-3">Saved Recordings</h2>
          <div class="recordings row"id="recordings">
          
          </div>


          從API中獲取上傳的文件:

          const recordingsContainer = document.getElementById('recordings');
          function fetchRecordings () {
          fetch('/recordings')
          .then((response) => response.json())
          .then((response) => {
            if (response.success && response.files) {
              //remove all previous recordings shown
              recordingsContainer.innerHTML = '';
              response.files.forEach((file) => {
                //create the recording element
                const recordingElement = createRecordingElement(file);
                //add it the the recordings container
                recordingsContainer.appendChild(recordingElement);
              })
            }
          })
          .catch((err) => console.error(err));
          }
          
          //create the recording element
          function createRecordingElement (file) {
          //container element
          const recordingElement = document.createElement('div');
          recordingElement.classList.add('col-lg-2', 'col', 'recording', 'mt-3');
          //audio element
          const audio = document.createElement('audio');
          audio.src = file;
          audio.onended = (e) => {
            //when the audio ends, change the image inside the button to play again
            e.target.nextElementSibling.firstElementChild.src = 'images/play.png';
          };
          recordingElement.appendChild(audio);
          //button element
          const playButton = document.createElement('button');
          playButton.classList.add('play-button', 'btn', 'border', 'shadow-sm', 'text-center', 'd-block', 'mx-auto');
          //image element inside button
          const playImage = document.createElement('img');
          playImage.src = '/images/play.png';
          playImage.classList.add('img-fluid');
          playButton.appendChild(playImage);
          //add event listener to the button to play the recording
          playButton.addEventListener('click', playRecording);
          recordingElement.appendChild(playButton);
          //return the container element
          return recordingElement;
          }
          
          function playRecording (e) {
          let button = e.target;
          if (button.tagName === 'IMG') {
            //get parent button
            button = button.parentElement;
          }
          //get audio sibling
          const audio = button.previousElementSibling;
          if (audio && audio.tagName === 'AUDIO') {
            if (audio.paused) {
              //if audio is paused, play it
              audio.play();
              //change the image inside the button to pause
              button.firstElementChild.src = 'images/pause.png';
            } else {
              //if audio is playing, pause it
              audio.pause();
              //change the image inside the button to play
              button.firstElementChild.src = 'images/play.png';
            }
          }
          }


          注意,在playRecording函數(shù)中,我們使用audio.paused來檢查音頻是否正在播放,如果音頻目前沒有播放,它將返回true。

          我們還使用了播放和暫停的圖標(biāo),這些圖標(biāo)將顯示在每個錄音中。你可以從Iconscout或GitHub資源庫中獲得這些圖標(biāo)。

          當(dāng)頁面加載和新的錄音被上傳時,我們將使用fetchRecordings。

          所以,在record.js的結(jié)尾和saveRecording的履行處理程序里面調(diào)用這個函數(shù),以代替TODO注釋。

          .then(() => {
          alert("Your recording is saved");
          //reset for next recording
          resetRecording();
          //fetch recordings
          fetchRecordings();
          })


          增加相關(guān)樣式:

          public/assets/css/index.css

          .play-button:hover {
           box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important;
          }
          
          .play-button {
           height: 8em;
           width: 8em;
           background-color: #5084d2;
          }


          最終測試


          現(xiàn)在都準(zhǔn)備好了。在你的瀏覽器中打開localhost:3000的網(wǎng)站,如果你之前上傳了任何錄音,你現(xiàn)在會看到它們。你也可以嘗試上傳新的,看到列表被更新。用戶現(xiàn)在可以錄制他們的聲音,保存或丟棄它們。用戶還可以查看所有上傳的錄音并播放它們。

          原文:https://www.sitepoint.com/mediastream-api-record-audio/

          常聽到剛開始做微課的老師說,錄制的微課沒有聲音,對于新手,怎么解決這個問題呢?

          錄制微課的過程中,涉及到的聲音無非就是兩種:一種是語音錄入,一種是錄制電腦的系統(tǒng)聲音。

          準(zhǔn)備工作:

          一、首先得檢查硬件設(shè)備

          1、臺式機(jī)的外接麥克風(fēng)是否連接正確,通常,麥克風(fēng)的插頭處是有顏色的(通常是粉紅色),插入臺式機(jī)電腦的聲卡對應(yīng)顏色的插孔就OK。

          2、筆記本電腦通常是內(nèi)置麥克風(fēng)(有個別款式的筆記本電腦是不帶內(nèi)置麥克風(fēng)的)

          二、檢查系統(tǒng)聲音設(shè)置

          確認(rèn)硬件設(shè)備無誤之后,還是無法錄制語音,通常和你所用的微課制作軟件沒什么關(guān)系,而是在電腦系統(tǒng)設(shè)置里的聲音設(shè)置可能不正確導(dǎo)致,下面是在win7下和xp下麥克風(fēng)錄音的設(shè)置方法,寫的比較詳細(xì),還配有截圖,大家可以對照著看一下。

          win7下麥克風(fēng)錄音設(shè)置方法步驟:

          http://jingyan.baidu.com/article/60ccbceb1f1d7f64cab19719.html

          Windows XP 下聲卡的錄音和麥克風(fēng)設(shè)置方法:

          http://wenku.baidu.com/view/1ce5f76327d3240c8447ef93.html

          測試

          打開操作系統(tǒng)里的 程序——附件——錄音機(jī),點(diǎn)擊開始錄音,然后你開始發(fā)聲,這時如果你看到綠色的音量指示器在跳動,那就說明麥克風(fēng)是設(shè)置好了的,回放聲音也就可以聽到剛才你錄入的語音了。

          三、錄音設(shè)備連接和設(shè)置好之后,在coursemaker 4.0里錄音就很簡單了

          點(diǎn)擊“開始”菜單里的“錄課”按鈕

          在彈出的菜單里,按照文字提示選擇要錄制的內(nèi)容就可以了

          語音:是指錄制麥克風(fēng)語音

          拍攝:可以在錄課時調(diào)用攝像頭拍攝

          鼠標(biāo)軌跡:錄課時錄制鼠標(biāo)軌跡(可以選擇多種軌跡光標(biāo))

          自動降噪:錄制語音時勾選此項(xiàng)

          錄制系統(tǒng)聲音:勾選上可以錄制電腦播放的聲音。

          四、如果您是在錄制PPT時要錄制語音

          要進(jìn)入設(shè)置菜單里,確認(rèn)錄音設(shè)備是否選中

          面,我們通過Web Audio API(網(wǎng)頁音頻接口)制作了一個簡單的剛琴小程序。(見《利用Web Audio API,使用純ECMAScript 6,無需第三方庫,開發(fā)一個鋼琴小程序》)

          我們現(xiàn)在看看Web Audio API(網(wǎng)頁音頻接口)是如何來處理錄音的。有些聲音是很難使用振蕩器來重現(xiàn)的,所以在許多情況下必須使用錄制的聲音來重現(xiàn)真實(shí)的聲音。格式可以是".MP3",".ogg",".wav"等,本人建議使用".MP3",因?yàn)樗禽p量級,有廣泛支持且具有很好的音質(zhì)。

          你不能像圖片一樣簡單地通過一個網(wǎng)址得到聲音。我們需要通過發(fā)送一個XMLHttpRequest請求來得到文件,解碼數(shù)據(jù),并放入緩沖區(qū)。

          讓我們看看構(gòu)造函數(shù): 我們收到我們在聲音類中所做的Context;收到的Url列表將被加載;一個空數(shù)組用于緩沖。

          我們有兩個方法:loadsound和loadAll。 loadAll循環(huán)通過URL列表來調(diào)用loadSound方法。它重要的是傳遞索引,我們才能在不管哪個請求首先加載下把緩沖的聲音放入正確的數(shù)組元素。這也讓我們看到最后一個請求意味著緩沖區(qū)加載的完成。

          然后你可以調(diào)用loaded()方法來做一些像隱藏加載指示器之類事情。最后在播放時通過getSoundByIndex(index) 方法從播放緩沖區(qū)中獲取相應(yīng)的值。

          decodeAudioData方法是新的語法,現(xiàn)在還不能在Safari中工作。

          context.decodeAudioData(audioData).then(function(decodedData) {

          // use the decoded data here

          });

          然后我們必須為聲音創(chuàng)建類。現(xiàn)在我們有完整的類來處理錄音:

          構(gòu)造函數(shù)接收了Context和Buffer緩沖。我們調(diào)用createBufferSource()方法來代替我們以前做的createOscillator()方法。我們使用getSoundByIndex()方法來獲取緩沖的音符(從緩沖數(shù)組中來的元素)。現(xiàn)在我們創(chuàng)建緩沖區(qū)(而不是振蕩器),設(shè)置緩沖區(qū),然后將其連接到目標(biāo)(或增益和其他濾波器)。

          現(xiàn)在我們要創(chuàng)建緩沖區(qū)實(shí)例并調(diào)用loadAll方法來加載所有的聲音到緩沖區(qū)。我們同時也要用getSoundById方法來獲取我們真正所需要的,把它傳送給聲音類并調(diào)用play()方法。ID可以作為按鈕上的數(shù)據(jù)屬性存儲,你點(diǎn)擊則播放聲音。

          這里有一個在線實(shí)例,使用了上述緩沖區(qū)、錄制的音符等技術(shù)(由于音頻資源較多,未完整實(shí)現(xiàn),僅供參考):

          http://www.ikinsoft.com/3ddemo/recoder.html


          主站蜘蛛池模板: 三上悠亚一区二区观看| 亚洲一区二区三区在线视频| 无码一区18禁3D| 国产亚洲一区二区手机在线观看 | 国产一区二区三区免费看| 午夜福利国产一区二区| 亚洲一区免费观看| 激情内射亚州一区二区三区爱妻| 乱码精品一区二区三区| 奇米精品一区二区三区在| 无码人妻精品一区二区三区9厂| 精品国产一区二区三区AV性色| 亚洲国产视频一区| 精品人妻AV一区二区三区| 国产成人无码AV一区二区 | 国产一区二区在线| 中文字幕乱码一区久久麻豆樱花| 亚欧色一区W666天堂| 麻豆一区二区99久久久久| 久久一区不卡中文字幕| 亚洲Av高清一区二区三区| 文中字幕一区二区三区视频播放 | 国产麻豆精品一区二区三区v视界| 精品一区二区AV天堂| 日本亚洲国产一区二区三区| 精品国产AⅤ一区二区三区4区 | 精品无人区一区二区三区| 精品欧洲AV无码一区二区男男| 一区高清大胆人体| 国产一区二区三区91| 日韩在线观看一区二区三区| 国产美女精品一区二区三区| 亚洲bt加勒比一区二区| 国产精品福利区一区二区三区四区| 日本精品一区二区三区在线视频一| 国产成人精品一区二区三区无码| 国产91精品一区二区麻豆网站 | 国产精品无圣光一区二区| 麻豆精品人妻一区二区三区蜜桃| 国产成人免费一区二区三区| 欧美日韩综合一区二区三区|