微信小程序-根据同声传译插件创建语音转文字的自定义插件

发布时间 2023-05-05 17:15:49作者: 流年sugar

使用了vant weapp组件

.js

// page/common/components/voice/voice.js
import Toast from '../../../../vant-weapp/dist/toast/toast';

//引入插件:微信同声传译
var plugin = requirePlugin("WechatVoice");
//获取全局唯一的语音识别管理器recordRecoManager
let manager = plugin.getRecordRecognitionManager();
var init;
Component({
  options: {
    multipleSlots: true, // 在组件定义时的选项中启用多slot支持
    styleIsolation: 'shared',//weapp组件样式可覆盖
  },
  /**
   * 组件的属性列表
   */
  properties: {
    //录音文字结果
    voiceValue: {
      type: String,
      value: ''
    },
    size: {
      type: Number,
      value: 20,
    },
  },

  /**
   * 组件的初始数据
   */
  data: {
    noRecordShow: false, //初始显示 未录音弹框是否显示
    recordLuzhiShow: false, //控制录制
    countNume: 0, // 倒计时
    filePath: '', // 临时语音录制文件地址
    duration: 0, // 录制时间
    isShow: false,
    text: '',
    error: '',
    styletsY: '',
  },
  attached: function () {
    //优先执行回调函数
    // this.initRecorder();
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 初始化录音各项回调函数
     */
    initRecorder: function () {
      var _this = this;
      manager.onRecognize = function (res) {
        console.log("current result", res.result)
      };
      //录音组件调用异常回调
      manager.onError = function (res) {
        Toast(res)
        _this.setData({
          // error: res,
          isShow: false,
        })
      };
    },

    /**
     * 显示录音弹框
     */
    show() {
      this.setData({
        isShow: true,
        noRecordShow: true
      })
    },

    /**
     * 开始录音
     */
    startRecordAudio() {
      clearInterval(init) //清除定时器
      this.setData({
        noRecordShow: false,
        recordLuzhiShow: true,
      });
      this.recordingTimer();
      
      var that=this;
      //录音开始回调
      manager.onStart = function (res) {
        console.log('recorder start', res)
      };
      //录音结果结束回调
      manager.onStop = function (res) {
        that.setData({
          duration: res.duration,
          text: res.result,
          voiceValue: that.properties.voiceValue + res.result,
        })
      }
      //开始录音
      manager.start({
        duration: 60000,
        lang: "zh_CN",
        // duration: this.data.duration, //指定录音的时长,单位 ms
        // sampleRate: 16000, //采样率
        // numberOfChannels: 1, //录音通道数
        // encodeBitRate: 96000, //编码码率
        // format: 'mp3', //音频格式,有效值 aac/mp3
        // frameSize: 50, //指定帧大小,单位 KB
      });
    },

    /**
     * 结束录音(调用manager.onStop()回调函数,将录音转为文字)
     */
    stopRecordAudio() {
      this.setData({
        recordLuzhiShow: false,
        // finishRecordShow: true,
        isShow: false,
      });
      
      this.recordingTimer(this.data.countNume);
      //结束录音
      manager.stop();
    },
    /**
     * 录音计时器
     * @param {*} time 
     */
    recordingTimer: function (time) {
      var that = this
      if (time == undefined) {
        //将计时器赋值给init
        init = setInterval(function () {
          var time = that.data.countNume + 1;
          that.setData({
            countNume: time
          })
        }, 1000);
      } else {
        clearInterval(init);
        that.setData({
          countNume:0,
        })
      }
    },
  }
})

注:注意同声传译插件的onStop()回调函数的调用位置,更改在其他地方使用,在同页面多次复用该组件的情况可能会导致数据错乱的问题

.json

{
  "component": true,
  "usingComponents": {
      "van-icon":"/vant-weapp/dist/icon/index",
      "van-action-sheet": "/vant-weapp/dist/action-sheet/index",
      "van-overlay":"/vant-weapp/dist/overlay/index"
  }
}

 

.wxml

<!--page/common/components/voice/voice.wxml-->
<van-icon name="/image/voice.png" bind:click="show" size="{{size}}" />
<van-overlay show="{{ isShow }}" bind:click="onClickHide" z-index="3">
    <view class="editWrapBox">
        <!-- 未录音 -->
        <view class="headerContentWrap" wx:if="{{noRecordShow}}">
            <view class="headerInWrapItem">
                <button class="luyinWrap" bindtap="startRecordAudio"><van-icon name="/image/voice2.png" color="white" size="35"  class="ico"/></button>
                <view class="actionName">点击录音</view>
            </view>
        </view>
        <!-- 录制语音中 -->
        <view wx:if="{{recordLuzhiShow}}">
            <view class="progressWrap">
                录音中(已录制<text class="numberSize">{{countNume}}s</text>),再次点击按钮即可停止录制
            </view>
            <view class="headerContentWrap">
                <view class="headerInWrapItem">
                    <view class="luyinOutWrap active"></view>
                    <button class="luyinWrap3" bindtap="stopRecordAudio"><van-icon name="/image/voice2.png" color="white" size="35"  class="ico"/></button>
                </view>
            </view>
        </view>
    </view>
</van-overlay>

 

.wxss

/* page/common/components/voice/voice.wxss */

.editWrapBox {
    /* background-color: #ffffff;
    margin-bottom: 10px;
    overflow: hidden;
    position: relative; */
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    z-index: 3;
}


.headerContentWrap {
    margin: 0 auto;
    padding: 30px 0;
    box-sizing: border-box;
    z-index: 5;
}

.headerInWrapItem {
    width: 100vw;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}

.luyinWrap,
.luyinWrap2,
.luyinWrap3 {
    width: 90px !important;
    height: 90px !important;
    line-height: 75px !important;
    border-radius: 50% !important;
    text-align: center !important;
    margin: 0;
}

.luyinWrap {
    background-color: #598EFE !important;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 1 !important;
}

.luyinWrap2 {
    background-color: #868AF0 !important;
}

.luyinWrap3 {
    background-color: #2D59DF;
    position: absolute;
    top: 25px;
    display: flex;
    align-items: center;
    justify-content: center;
}



.icon {
    font-size: 35px;
    color: #ffffff;
}

.icon-bofanganniu
{
    font-size: 25px;
    color: #ffffff;
}

.actionName {
    margin-top: 14px;
    font-size: 14px;
    color: white;
}

.numberSize,
.delText {
    color: #E50000;
}

.delText {
    font-size: 14px;
    width: 55px;
    height: 55px;
    text-align: center;
    line-height: 55px;
    margin-top: 27px;
    border: 1px solid #E50000;
    border-radius: 50%;
}

.progressWrap {
    width: 100vw;
    height: 40px;
    line-height: 40px;
    margin: 0px auto;
    /* background-color: #BCCDFF; */
    font-size: 14px;
    text-align: center;
    /* color: #333333; */
    color: #BCCDFF;
    z-index: 5;
}

.luyinOutWrap.active {
    background-color: #BCCDFF;
    opacity: 1;
    animation: scale 2.5s infinite ease alternate;
}

.luyinOutWrap {
    width: 120px;
    height: 120px;
    text-align: center;
    margin: 10px auto;
    border-radius: 50%;
}

@keyframes scale {
    0% {
        opacity: 1
    }

    25% {
        opacity: 0.75
    }

    45% {
        opacity: 0.5
    }

    50% {
        opacity: 0.25
    }

    75% {
        opacity: 0.5
    }

    85% {
        opacity: 0.75
    }

    100% {
        opacity: 1
    }

}

 

其他页面引用

.json

 .wxml