欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

微信小程序?qū)崿F(xiàn)語音錄制,上傳,播放 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

微信小程序?qū)崿F(xiàn)語音錄制,上傳,播放

發(fā)表時間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):164

記錄技術(shù),分享技術(shù),做個偉大的搬運工。

框架選用

開發(fā)微信小程序,使用的是unapp。 為什么要選用這個,因為他比較成熟,之前用過mpvue,kbone都是特別的不太成熟。后來經(jīng)過各種選型選定了uniapp。


遇到的問題
  • 錄音授權(quán)。
  • 長按錄音,判斷手指是否劃出長按的區(qū)域
  • 文件上傳。
  • 多錄制語音播放。

初始化工作
  1. 定義全局錄音對象和audio對象,并且格式化自己想要的音頻格式
const recorderManager = uni.getRecorderManager(); // 創(chuàng)建錄音對象
const audioContext = wx.createInnerAudioContext(); // 創(chuàng)建audio對象
const options = {
    duration: 600000, //指定錄音的時長,單位 ms,最大為10分鐘(600000),默認為1分鐘(60000)
    sampleRate: 16000, //采樣率
    numberOfChannels: 1, //錄音通道數(shù)
    encodeBitRate: 96000, //編碼碼率
    format: 'mp3', //音頻格式,有效值 aac/mp3 等
    frameSize: 50 //指定幀大小,單位 KB
};
復(fù)制代碼

錄音授權(quán)

錄音收取主要從兩個方面考慮

  1. 申請授權(quán)用戶直接同意授權(quán)
  2. 用戶拒絕授權(quán)后,打開設(shè)置,用戶收到授權(quán)。
uni.authorize({
    scope: 'scope.record',
    success() {
        // 用戶已經(jīng)同意授權(quán),可以進行錄音
    },
    fail() {
    	// 此處用戶授權(quán)失敗,需要打開設(shè)置,去手動授權(quán)。  在某些情況下openSetting無法打開
        // 可以通過fail的方式,通過彈窗用戶打開設(shè)置。
        uni.openSetting({
            success: res => {
            	// 沒有授權(quán)的情況下,彈窗提示
                if (!res.authSetting['scope.record']) {
                    //未設(shè)置錄音授權(quán)
                    uni.showModal({
                        title: '提示',
                        content: '您未授權(quán)錄音,功能將無法使用',
                        showCancel: false
                    });
                } else {
                    // 第二次才成功授權(quán)
                    // 用戶已經(jīng)同意授權(quán),可以進行錄音
                }
            },
            fail: function() {
                uni.showModal({
                    title: '提示',
                    content: '您未授權(quán)錄音,功能將無法使用',
                    showCancel: false,
                    success: function(res) {
                        uni.openSetting();
                    }
                });
            }
        });
    }
});

復(fù)制代碼

官方api鏈接

接口調(diào)整鏈接


長按錄音 / 滑動區(qū)域 / 停止長按

uniapp中的方法
@longpress 長按(手指觸摸超過350ms)  
@longtap 長按  
@tap 點擊  
@touchcancel 手指觸摸被打斷,如來電提醒,彈窗  
@touchend 手指觸摸動作結(jié)束,如松開按鈕  
@touchmove 手指觸摸后移動  
@touchstart 手指觸摸動作開始 
復(fù)制代碼

錄制操作
  1. 獲取當(dāng)前點擊元素距離頂部的距離
  • 長按的同時,要開始計時,已經(jīng)授權(quán)的時候要開始錄制語音。
// 小程序中獲取當(dāng)前點擊元素的距離和其他的有所不同,以下是獲取的方法
const query = uni.createSelectorQuery().in(this);
  query
      .select('.record-button')
      .boundingClientRect(data => {
          // data 當(dāng)前元素的各個信息
      })
      .exec();
復(fù)制代碼
  1. 通過event獲取當(dāng)前各項信息
  • 滑動超出的時候要進行停止錄音,并且要清空計時器。
  • 滑回來的時候要繼續(xù)錄音,繼續(xù)定時器。
  • 此處需要加個中間狀態(tài),通過監(jiān)聽來進行繼續(xù)錄制錄音和停止錄制語音
let touches = e.touches[0];
  // 超出的時候
  if (touches.pageY < this.reocrdLocation.top) {
      clearInterval(this.timerInfo);
      recorderManager.pause();
  } else {
      recorderManager.resume();
  }
復(fù)制代碼

停止長按
  • 判斷錄音時長太短的話,不進行上傳,
  • 符合條件的進行上傳,并且清空定時器,停止錄制
recorderManager.stop();
// 監(jiān)聽停止事件
recorderManager.onStop(res => {
    if (this.duration < 1) {
        uni.showToast({
            title: '錄制時間太短',
            duration: 1000,
            icon: 'none'
        });
        return;
    }
    
    // 符合條件的,推進數(shù)組。
   

    this.voiceList.push({
        size: res.fileSize, // 本地的進度
        progress: -1,//-1 沒有上傳, -100 上傳失敗, 100 上傳成功, 0 ~ 100上傳中
        path: res.tempFilePath, // 線上路徑
        duration: this.duration // 錄音時長
    });
    // 核對上傳
    this.checkUploadVoice();
});

clearInterval(this.timerInfo);
復(fù)制代碼


文件上傳
  • 通過設(shè)置每個錄音的狀態(tài),來記錄各個狀態(tài)(-1 沒有上傳, -100 上傳失敗, 100 上傳成功, 0 ~ 100上傳中)。
  • 上傳失敗可以實現(xiàn)重新上傳。所以上傳文件前,要進行核對文件(核對各個狀態(tài))。
let obj;
for (let i = 0; i < this.voiceList.length; i++) {
    let item = this.voiceList[i];
    if (item.progress == -1 || item.progress == -100) {
        obj = await this.uploadFiles(item, i); // 等待文件上傳完成后,獲取信息
        // 修改語音數(shù)組 通過set
        this.$set(this.voiceList, i, {
            name: item.name,
            size: item.size,
            progress: obj.progress,
            path: obj.path, //
            duration: item.duration,
            nowPlay: false,
            text: '',
            translateStatus: false, // 此處記錄是否轉(zhuǎn)化為文字
        });

        this.duration = 0; // 文件上傳后,時間記錄要清0
    }
}


// 上傳文件
uploadFiles(item, i) {
    return new Promise((resolve, reject) => {
        const uploadTask = uni.uploadFile({
            url: url, // 上傳圖片的地址
            filePath: item.path, // 錄音后拿到的地址
            name: 'file',
            header: {
                'Content-Type': 'multipart/form-data',
                accept: 'application/json'
            },
            success: upRes => {
                console.log(upRes);
                let dataInfo = JSON.parse(upRes.data);
                let { code, data } = dataInfo;
                // 成功后要返回成功的信息
                resolve({
                    path: data.fileUrl,
                    progress: 100
                });
            },
            fail: function(err) {
            	// 上傳失敗的時候要記錄狀態(tài)
                resolve({
                    path: '',
                    progress: -100
                });
            }
        });

        uploadTask.onProgressUpdate(res => {
           // 此處獲取上傳的進度,并且實時展示
           this.$set(this.voiceList, {
                    name: item.name,
                    size: item.size,
                    progress: res.progress,
                    path: item.path,
                    duration: item.duration
                });
            // console.log('上傳進度', res.progress);
            // console.log('已經(jīng)上傳的數(shù)據(jù)長度', res.totalBytesSent);
            // console.log(
            //     '預(yù)期需要上傳的數(shù)據(jù)總長度',
            //     res.totalBytesExpectedToSend
            // );
        });
    });
},

復(fù)制代碼

多條錄音播放
  • 播放的時候只保持一條正在播放(最主要的問題)
  • 停止其他正在播放的語音
  • 播放當(dāng)前點擊的語音
// 播放語音
async playVoice(item, index) {
    uni.showLoading({
        title: '錄音播放加載中'
    });
    //  同時點擊當(dāng)前的語音兩次,需要先把上一個停止到,再進行播放新的
    if (item.nowPlay && this.nowPlayItem.nowPlay) {
        this.stopVoice(item);
        return;
    }

    // 兩條播放的語音不一樣, 停止上一條,改變播放的狀態(tài),然后播放當(dāng)前的
    if (!item.nowPlay && this.nowPlayItem.nowPlay) {
        let status = await this.stopVoice(item);
        let obj = Object.assign({}, this.nowPlayItem.item, {
            nowPlay: false
        });
        
        
        /**
        // 記錄全局播放的音頻(停止上次點擊的音頻,播放新的點擊的音頻,兩次點擊的音頻不一樣)
        nowPlayItem: {
              index: -1, // index 為當(dāng)前播放的索引值
              nowPlay: false, // 當(dāng)前是否有正在播放的語音
              item: null
          },
        */

        this.$set(this.voiceList, this.nowPlayItem.index, obj);
    }

    audioContext.src = http://www.wxapp-union.com/item.path; // 播放的錄音地址
    audioContext.play();
    this.nowPlayItem.index = index;
    this.nowPlayItem.item = item;

    // 開始播放監(jiān)聽
    audioContext.onPlay(res => {
        uni.hideLoading();
        console.log('play');
        item.nowPlay = true;
        this.nowPlayItem.nowPlay = true;
    });

    // 停止播放監(jiān)聽(當(dāng)前的播放是否停止)
    audioContext.onPause(res => {
        console.log('pause');
        item.nowPlay = false;
        this.nowPlayItem.nowPlay = false;
        // 監(jiān)聽音頻,要和取消監(jiān)聽同時存在,
        audioContext.offPlay();
        audioContext.offPause();
        audioContext.offStop();
        audioContext.offEnded();
    });

    // 監(jiān)聽音頻自然播放至結(jié)束的事件,真機調(diào)試會存在問題,微信開發(fā)者工具這塊不會有問題
    audioContext.onEnded(res => {
        console.log('ended');
        item.nowPlay = false;
        this.nowPlayItem.nowPlay = false;
        // 監(jiān)聽音頻,要和取消監(jiān)聽同時存在,
        audioContext.offPlay();
        audioContext.offPause();
        audioContext.offStop();
        audioContext.offEnded();
    });

    audioContext.onError(res => {
        console.log('error');
        // 播放音頻失敗的回調(diào)
        console.log(res);
    });
},
// 只有當(dāng)前的播放停止時,才進行下一個播放開始
stopVoice(item) {
    return new Promise((resolve, reject) => {
        audioContext.stop();
        audioContext.onStop(res => {
            // 播放音頻失敗的回調(diào)
            this.nowPlayItem.nowPlay = false;
            if (item) {
                item.nowPlay = false;
            }
            audioContext.offPlay();
            audioContext.offPause();
            audioContext.offStop();
            audioContext.offEnded();

            resolve(true);
        });
    });
},
復(fù)制代碼

此處容易出錯的地方

  1. 音頻監(jiān)聽事件要和取消事件同時存在
  2. 改變語音播放狀態(tài)的時候,必須要等到上一條停止,才可以進行后續(xù)工作

總結(jié)
  1. 模擬器和真機的差別還是挺大的,真機上各個事件比模擬器會慢一點。
  2. 學(xué)海無涯,持之以恒。