小程序錄音功能實現 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

小程序錄音功能實現

發表時(shí)間:2021-3-15

發布人(rén):融晨科技

浏覽次數:63

前言

在(zài)開發小程序過程中,有一個(gè)實現錄音功能并播放錄音,将錄音上(shàng)傳至服務器的(de)需求。開發過程中使用了(le/liǎo)Taro框架,錄音功能通過 Taro.getRecorderManager() 接口實現,上(shàng)傳錄音至服務器通過 Taro.uploadFile 接口實現,播放錄音使用 Taro.createInnerAudioContext() 接口實現。下面就(jiù)詳細介紹整個(gè)流程是(shì)如何實現的(de)。

小程序錄音

首先獲取錄音管理器模塊:

const recorderManager = Taro.getRecorderManager();
複制代碼

在(zài)組件挂載完畢時(shí)注冊錄音監聽事件:

useEffect(() => {
	// 監聽錄音開始
    recorderManager.onStart(() => {
      console.log('開始錄音');
    });
	// 監聽錄音暫停
    recorderManager.onPause(() => {
      console.log('暫停錄音');
    });
	// 監聽錄音繼續
    recorderManager.onResume(() => {
      console.log('繼續錄音');
    });
	// 監聽錄音停止
    recorderManager.onStop((res) => {
      if (res.duration < 1000) {
        Taro.showToast({
          title: '錄音時(shí)間太短',
          duration: 1000,
          icon: 'none',
        });
      } else {
        console.log('停止錄音');
        fileUpload(res.tempFilePath);
      }
    });

    recorderManager.onError(() => {
      Taro.showToast({
        title: '錄音失敗!',
        duration: 1000,
        icon: 'none',
      });
    });
  }, []);
複制代碼

在(zài)錄音 onStop 的(de)回調函數中,我們可以(yǐ)獲取到(dào)錄音的(de)臨時(shí)地(dì / de)址 res.tempFilePath ,但這(zhè)個(gè)地(dì / de)址是(shì)有有效期限的(de),所以(yǐ)我們需要(yào / yāo)将這(zhè)個(gè)錄音上(shàng)傳至服務器後台,進行保存,後續才能正常使用。

onStop 回調函數中我們調用了(le/liǎo) fileUpload 函數實現文件上(shàng)傳, fileUpload 函數的(de)實現如下:

const fileUpload = (tempFilePath) => {
    Taro.uploadFile({
      url: 'http://127.0.0.1:7001/record', // 服務器地(dì / de)址
      filePath: tempFilePath,
      name: 'file', // 這(zhè)個(gè)随便填
      header: {
        'content-type': 'multipart/form-data', // 格式必須是(shì)這(zhè)個(gè)
        Authorization: Taro.getStorageSync('token'),
      },
      // formData用于(yú)傳輸除文件以(yǐ)外的(de)一些信息
      formData: {
        record_name: '朗誦作品',
        poem_id: poemInfo.id,
        category: poemInfo.category,
      },
      success: (res) => {
        console.log(res);
        const url = res.data;
        playAudio(url); // 播放錄音
      },
      fail: (error) => {
        console.log('failed!');
        console.error(error);
      },
    });
  };
複制代碼

需要(yào / yāo)注意的(de)點是(shì): header 中的(de) content-type 必須是(shì) multipart/form-data 。

錄音事件的(de)處理

第一次點擊 handleClick 就(jiù)會觸發開始錄音,之(zhī)後會通過當前狀态判斷是(shì)暫停錄音還是(shì)繼續錄音。 handleComplete 用于(yú)停止錄音。

const handleClick = () => {
    const curPause = pause;
    setPause(!curPause);

    if (firstRecord) {
      setfirstRecord(false);

      recorderManager.start({
        duration: 60000,
        sampleRate: 44100,
        numberOfChannels: 1,
        encodeBitRate: 192000,
        format: 'mp3',
        frameSize: 50,
      });

      Taro.showToast({
        title: '開始錄音',
        duration: 1000,
        icon: 'none',
      });

    } else {
      if (curPause) {
        recorderManager.pause(); // 暫停錄音
      } else {
        recorderManager.resume(); // 繼續錄音
      }
    }
  };

  const handleComplete = () => {
    recorderManager.stop(); // 停止錄音
  };
複制代碼

後台實現錄音存儲并返回錄音地(dì / de)址

網上(shàng)大(dà)多數博客都沒有涉及這(zhè)塊内容,下面就(jiù)介紹一下如何實現,後台框架我用的(de)是(shì)阿裏的(de) egg.js 。

文件上(shàng)傳需要(yào / yāo)配置的(de)東西可見官方文檔: egg.js文件上(shàng)傳 。我們這(zhè)裏使用它的(de)第一種 File 模式來(lái)實現。

因爲(wéi / wèi) egg.js 框架内置了(le/liǎo) Multipart 插件,可以(yǐ)解析上(shàng)傳的(de) multipart/form-data 類型的(de)數據。

首先,現在(zài)配置文件 config.default.js 中寫入 multipart 配置:

module.exports = (app) => {
  const config = (exports = {});
  
  ...

  config.multipart = {
    mode: 'file',
    fileSize: '50mb',
  }
  ...

  return {
    ...config,
    ...userConfig,
  };
};
複制代碼

然後,在(zài) router.js 中定義路由:

// 提交錄音
router.post('/record', auth, controller.record.postRecord);
複制代碼

在(zài) controller 目錄下定義 record.js 文件寫入如下内容:

const Controller = require('egg').Controller;

class RecordController extends Controller {
  async postRecord() {
    const { ctx } = this;
    const file = ctx.request.files[0];
    const { record_name, poem_id, category } = ctx.request.body;
    
    const res = await ctx.service.record.postRecord(file, record_name, poem_id, category);

    ctx.body = res;
  }
}

module.exports = RecordController;
複制代碼

在(zài) service 目錄下定義 record.js 寫入具體實現:

const Service = require('egg').Service;
let OSS = require('ali-oss');

let aliInfo = {
  // https://help.aliyun.com/document_detail/31837.html
  region: 'oss-cn-guangzhou',
  bucket: 'poem-mini-program',
  accessKeyId: 'xxx', // 填入阿裏雲的(de)accessKeyId
  accessKeySecret: 'xxx', // 填入阿裏雲的(de)accessKeySecret
};

let client = new OSS(aliInfo);

class RecordService extends Service {
  async postRecord(file, record_name, poem_id, category) {
    const url = await this.uploadOSS(file);
    await this.updateRecord(url, record_name, poem_id, category);

    return url;
  }

  async uploadOSS(file) {
    const { ctx } = this;

    let result;
    try {
      // 處理文件,比如上(shàng)傳到(dào)雲端
      result = await client.put(file.filename, file.filepath);
    } finally {
      // 需要(yào / yāo)删除臨時(shí)文件
      await ctx.cleanupRequestFiles();
    }
    return result.url;
  }

  async updateRecord(url, record_name, poem_id, category) {
    const { ctx } = this;

    console.log('從ctx.locals中取openid');
    console.log(ctx.locals.openid);
    const openid = ctx.locals.openid;

    // 将用戶信息記錄到(dào)數據庫中
    const res = await ctx.model.Record.create({
      record_name: record_name,
      record_url: url,
      poem_id: poem_id,
      category: category,
      openid: openid,
    });
  }
}
module.exports = RecordService;

複制代碼

這(zhè)裏需要(yào / yāo)注意的(de)是(shì):

  • 需要(yào / yāo)注冊阿裏雲賬号,并在(zài)對象存儲那裏新建一個(gè)存儲桶用于(yú)存放音頻,也(yě)就(jiù)是(shì)雲存儲的(de)實現。
  • 需要(yào / yāo)安裝 ali-oss npm包,用于(yú)連接阿裏雲對象存儲。在(zài)後台接收到(dào)前端上(shàng)傳的(de)臨時(shí)文件後,就(jiù)會将音頻上(shàng)傳至阿裏雲對象存儲中( client.put )。

播放錄音

細心的(de)小夥伴可以(yǐ)注意到(dào)在(zài)使用 Taro.uploadFile 接口上(shàng)傳錄音後,在(zài) success 回調中調用了(le/liǎo) playAudio 函數用于(yú)播放音頻,接下來(lái)講一下播放音頻是(shì)如何實現的(de)。

首先,使用 Taro.createInnerAudioContext 獲取 audio 的(de)上(shàng)下文對象:

const innerAudioText = Taro.createInnerAudioContext();
複制代碼

和(hé / huò)錄音一樣,在(zài)組件挂載完成時(shí),注冊監聽事件:

useEffect(() => {
    innerAudioText.onPlay(() => {
      console.log('開始播放');
    });

    innerAudioText.onError((e) => {
      console.log('播放異常');
      console.log(e);
    });
  }, []);
複制代碼

在(zài)錄音文件上(shàng)傳成功後,調用 playAudio 方法用于(yú)播放錄音:

const playAudio = (url) => {
  innerAudioText.autoplay = true;
  innerAudioText.src = http://www.wxapp-union.com/url;
};
複制代碼

在(zài) src 被賦予值的(de)時(shí)候,錄音就(jiù)會開始播放。

總結

以(yǐ)上(shàng)就(jiù)是(shì)整個(gè)錄音功能和(hé / huò)錄音播放功能實現的(de)整個(gè)流程,如有疑問歡迎大(dà)家一起交流。

相關案例查看更多