本篇文章主要介绍一下以下功能:

用小程序实现录音功能,在本地播放,提交服务端,服务端播放。

中间遇到了一些坑,找到了一些解决方法,如果有更优的解决方案希望你能在评论留言,一起加油。

1.小程序端

前端展示页面,小程序采用数据绑定方式,这里正在录音和正在播放的状态切换,用两张图根据录音状态和播放状态切换,这里就不多说了。

长按开始录音,触发录音事件,松手执行录音结束,将录音结果保存在本地。

/**

* 开始录音

*/

startRecord: function () {

var that = this

that.setData({

isRecording: true,

});

whisper.startRecord({

success(result) {

that.setData({

isRecording: false,

});

console.log('录音成功:', result);

console.log('录音成功:', result.tempFilePath);

//提交录音

var src = result.tempFilePath;

var name = 'record'

repair.uploadRecord(src, name, (res) => {

that.data.recordObj.record = res;

});

},

fail(error) {

console.log('录音失败:', error);

},

process() {

that.setData({

duration: whisper.getRecordDuration(),

});

},

compelete() {

},

});

},

/**

* 停止录音

*/

stopRecord: function () {

var that = this;

whisper.stopRecord({

success(result) {

that.setData({

isRecording: false,

});

console.log('停止录音:', result);

},

fail(error) {

console.log('停止录音失败:', error);

}

});

},

/**

* 播放录音

*/

play: function () {

var that = this

that.setData({

isPlaying: true,

});

whisper.playRecord({

src: whisper.getRecordSrc(),

success(result) {

that.setData({

isPlaying: false,

});

console.log('播放/暂停成功:', result);

},

fail(error) {

that.setData({

isPlaying: false,

});

console.log('播放/暂停失败:', error);

}

});

},

在录音结束后,执行success的回调函数,上传录音文件到服务器,注意微信小程序的录音文件是silk格式,这是一大坑,在服务端需要处理一下,后面再说。

具体的上传在model层。

//上传录音

uploadRecord(src, name, callback){

var params = {

url:'repair/record',

filePath: src,

name: name,

formData: {

'name': name

},

sCallback: function (data) {

callback && callback(data);

}

};

this.upload(params);

}

录音类也贴一下

var noop = function noop() { };

var recorder = {

};

/***

* @class

* 表示请求过程中发生的异常

*/

var RecordError = (function () {

function RecordError(message) {

Error.call(this, message);

this.message = message;

}

RecordError.prototype = new Error();

RecordError.prototype.constructor = RecordError;

return RecordError;

})();

function startRecord(options) {

if (typeof options !== 'object') {

var message = '请求传参应为 object 类型,但实际传了 ' + (typeof options) + ' 类型';

throw new RecordError(message);

}

var process = options.process;

var success = options.success || noop;

var fail = options.fail || noop;

var complete = options.complete || noop;

if (typeof process !== 'function') {

var message = '刷新Ui函数不存在';

throw new RecordError(message);

}

// 成功回调

var callSuccess = function () {

success.apply(null, arguments);

complete.apply(null, arguments);

};

// 失败回调

var callFail = function (error) {

fail.call(null, error);

complete.call(null, error);

};

// 初始化录音器

initRecorder();

// 实际进行请求的方法

doRecord();

// 实际进行请求的方法

function doRecord() {

console.log("开始录音")

recorder.timer = setInterval(function () {

recorder.duration += 1;

process();

if (recorder.duration >= recorder.maxDuration && recorder.timer) {

clearInterval(recorder.timer);

}

}, 1000);

wx.startRecord({

success: function (res) {

if (res.tempFilePath) {

recorder.src = res.tempFilePath;

callSuccess.apply(null, arguments);

return ;

} else {

message = '录音文件保存失败';

var error = new RecordError(message);

options.fail(error);

}

callFail(error);

},

fail: callFail,

complete: complete,

});

};

// 初始化录音器

function initRecorder() {

recorder = {

maxDuration: 60,

duration: 0,

src: null,

timer: null,

};

}

};

function stopRecord(options) {

if (typeof options !== 'object') {

var message = '请求传参应为 object 类型,但实际传了 ' + (typeof options) + ' 类型';

throw new RecordError(message);

}

var success = options.success || noop;

var fail = options.fail || noop;

var complete = options.complete || noop;

// 成功回调

var callSuccess = function () {

success.apply(null, arguments);

complete.apply(null, arguments);

};

// 失败回调

var callFail = function (error) {

fail.call(null, error);

complete.call(null, error);

};

doStopRecord();

// 实际进行请求的方法

function doStopRecord() {

wx.stopRecord({

success: function (res) {

if (recorder.timer) {

clearInterval(recorder.timer);

}

callSuccess.apply(null, arguments);

},

fail: callFail,

complete: complete,

});

};

};

function getRecordDuration() {

return recorder.duration || 0;

}

function getRecordSrc() {

return recorder.src || null;

}

module.exports = {

RecordError: RecordError,

startRecord: startRecord,

stopRecord: stopRecord,

getRecordDuration: getRecordDuration,

getRecordSrc: getRecordSrc,

};

播放类

var noop = function noop() { };

var player = {

src: null,

};

/***

* @class

* 表示请求过程中发生的异常

*/

var PlayError = (function () {

function PlayError(message) {

Error.call(this, message);

this.message = message;

}

PlayError.prototype = new Error();

PlayError.prototype.constructor = PlayError;

return PlayError;

})();

function play(options) {

if (typeof options !== 'object') {

var message = '请求传参应为 object 类型,但实际传了 ' + (typeof options) + ' 类型';

throw new PlayError(message);

}

if (!options.src) {

var message = '无资源';

var error = new PlayError(message);

options.fail(error);

return;

}

var process = options.process || noop;

var success = options.success || noop;

var fail = options.fail || noop;

var complete = options.complete || noop;

// 成功回调

var callSuccess = function () {

success.apply(null, arguments);

complete.apply(null, arguments);

};

// 失败回调

var callFail = function (error) {

fail.call(null, error);

complete.call(null, error);

};

if (!player.src || player.src != options.src) {

if (player.src) {

doStop(false);

}

doPlay();

} else {

doStop(true);

}

// 实际进行请求的方法

function doPlay() {

player.src = options.src;

console.log("开始播放" + player.src);

wx.playVoice({

filePath: player.src,

success: function (res) {

// success

console.log("播放结束" + player.src);

player.src = null,

callSuccess.apply(null, arguments);

},

fail: callFail,

complete: complete,

})

};

// 实际进行请求的方法

function doStop(isCallbackOn) {

wx.stopVoice({

success: function () {

console.log("停止播放" + player.src);

player.src = null;

isCallbackOn ? callSuccess.apply(null, arguments) : noop();

},

fail: isCallbackOn ? callFail : noop,

complete: isCallbackOn ? complete : noop,

});

};

};

module.exports = {

PlayError: PlayError,

playRecord: play,

};

ok,前端完成,转向服务端

2.服务端

后端用的是PHP的TP5框架,接收到的silk文件想要在浏览器上播放,我刚开始是想的转码MP3,在网上找了些资料,基本都指向了kn007大神的博客,写了个demo,Silk v3编码格式转码MP3终于实现了,结果发现小程序的silk不是silk V3,哭晕在厕所,这里可能有我没理解的,有人实现了希望可以留言。

然后,我一同事提醒我webm格式的可以直接播放的,囧。那就没的说了,直接base64解码成webm格式。

/**

* 报修录音

* @url /repair/record

* @http post

*/

public function uploadRecord()

{

$name = input('post.name');

if($_FILES[$name]["error"] > 0){

throw new Exception("Error: " . $_FILES[$name]["error"]);

}else{

$file = request()->file($name);

$info = $file->move(ROOT_PATH . 'public' . DS . 'record/'.$this->mainID);

$path = $info->getSaveName();

$base = ROOT_PATH . 'public' . DS;

$silk = $base . 'record/' . $this->mainID . '/' . $path;

$webm = str_replace("silk","webm",$silk);

$returnWebm = str_replace("silk","webm",$path);

$content = file_get_contents($silk);

$baseSilk = base64_decode(str_replace("data:audio/webm;base64,", '', $content));

file_put_contents($webm,$baseSilk);

}

return $returnWebm;

}

也贴一下wins环境下,用silk_v3_decoder.exe转码MP3的测试代码吧,具体的可以看下kn007大神的博客。

public function test()

{

$base = ROOT_PATH . 'public' . DS;

$file = $base.'record\\song1.silk';

$type = $base.'record\\song.pcm';

$res = $base.'record\\song.mp3';

$cmd = "{$base}silk\\windows\\silk_v3_decoder.exe $file $type" ;

exec($cmd, $out);

$cmd1 = "{$base}silk\\windows\\ffmpeg.exe -y -f s16le -ar 24000 -ac 1 -i $type $res";

exec($cmd1,$out1);

}

就这吧。

java silk v3 转码,小程序、录音、TP5、转码、silk相关推荐

  1. 计算机毕业设计Java智慧防疫上报系统小程序端(源码+系统+mysql数据库+Lw文档)

    计算机毕业设计Java智慧防疫上报系统小程序端(源码+系统+mysql数据库+Lw文档) 计算机毕业设计Java智慧防疫上报系统小程序端(源码+系统+mysql数据库+Lw文档) 项目架构:B/S架构 ...

  2. 闲来无事,用java写了一个魔方小程序。附源码

    闲来无事,用java写了一个魔方小程序.附源码 使用三维数组.相对来说还是简单.呵呵. import java.util.ArrayList; import java.util.List; impor ...

  3. java实现魔方_闲来无事,用java写了一个魔方小程序。附源码 | 学步园

    闲来无事,用java写了一个魔方小程序.附源码 使用三维数组.相对来说还是简单.呵呵. import java.util.ArrayList; import java.util.List; impor ...

  4. 计算机毕业设计Java信用卡增值业务系统小程序管理端(源码+系统+mysql数据库+lw文档

    计算机毕业设计Java信用卡增值业务系统小程序管理端(源码+系统+mysql数据库+lw文档 计算机毕业设计Java信用卡增值业务系统小程序管理端(源码+系统+mysql数据库+lw文档) 本源码技术 ...

  5. java silk转mp3_微信小程序录音文件格式silk遇到的问题及解决方法

    不好意思,误导大家了,这种将silk解密的方式只是在小程序测试的时候可以,上线以后这种方法是不行的,还是需要使用解密转码.参见:https://github.com/kn007/silk-v3-dec ...

  6. php silk v3 decoder,微信小程序语音搜索踩坑:silk文件格式转换,在PHP中使用

    直接调用微信小程序录音接口,然后上传到服务器,百度语音的接口是识别不了这种格式的文件,那么问题来了 一.如何转码?ffmpeg? 二.如何在PHP中使用? 本文将要解决这两个问题. 用到的第三方工具: ...

  7. 芝麻动态码-小程序动态二维码生成

    小程序的二维码,是静态的,在公众号里传播的时候,效果不太好,但是因为小程序的logo 很大,可以容纳很多的内容,所以就希望中间的部分可以动态显示. 经过我们的验证,是可行的,来几张效果图 1. 二次元 ...

  8. 收款码合并有什么弊端_合并收款码小程序,合并收款码助手

    之前就发了支付宝和微信的收款码合并,我以为上次教程很简单应该都会制作,不料还是有不少人不会做.这次新增QQ收款码合并,同时也把教程写的更加详细希望大家喜欢哈. 点击下方小程序开始合成制作 ↓↓↓↓ 常 ...

  9. 啦啦外卖公众号+小程序 V43.0开源至尊独立版+独家用户授权升级+小程序端+APP源码+小程序端VUE源码安装教程

    啦啦外卖跑腿平台开源至尊独立稳定版公众号+小程序 V43.0版系统为独立开源版,最大优势全开源,使用的都知道该系统功能非常强大,是目前外卖平台功能最全的一套系统.拿来即用,也非常合适做二开的朋友,包括 ...

  10. 微信小程序录音 第一篇 (基于微信小程序及百度AI的 人员语音识别转文字显示小程序)

    基于微信小程序及百度AI的 人员语音识别转文字显示小程序 基于微信小程序及百度AI的 人员语音识别转文字显示小程序主要分3篇 1.微信小程序录音篇(小程序基于wx.startRecord()微信语音录 ...

最新文章

  1. SVD(奇异值分解)小结
  2. Android studio下将项目代码上传至github包括更新,同步,创建依赖
  3. andoid 打包短信发送到gmail邮箱
  4. Perl迎来25岁生日
  5. 提高SQL执行效率的几点建议
  6. 使用Power Designer(PD)创建数据库模型、数据库表
  7. 什么作用计算机辅助工艺,什么是CAPP技术(计算机辅助工艺过程设计)
  8. 【SQLMap工具-1】SQLMap简介及简单应用实例
  9. 后端日志【22】:时间过的很快,坚持的第7.3个月过去了,我有什么变化?
  10. 腾讯微博开放平台开发吐槽
  11. 小米便签产品级的源码
  12. 2020年度中职组“网络空间安全”赛项xx市竞赛任务书
  13. 基于51单片机的电子密码锁设计
  14. 让数据快速使用, “无代码”新贵Nextion BI高效解决企业“BI”难
  15. java图片加文字水印_JAVA实现图片的修改,添加文字水印效果
  16. 为你描绘精确的太极图
  17. 29. 人类将如何变革--走出金字塔模型(上)
  18. autojs微博_autojs使用intent打开新浪微博的用户任务中心scheme的详细过程
  19. 如何开源,决定于对开源的认识 ———— 《OpenSources:来自开源革命的呼声》书评...
  20. iPhone手机查找朋友怎么用?添加对方号码,瞬间变成追踪器

热门文章

  1. 建设网站-个人电子图书馆
  2. NFS(网络文件系统)
  3. 使用 sudo nautilus 进入ubuntu 文件管理器。可以随意复制,删除,粘贴,无权限限制
  4. VB.NET CHART
  5. 11 wifi 驱动 进阶 http://blog.csdn.net/wh_19910525/article/details/7393615
  6. owc报表控件 数据透视表_将数据透视图标题链接到报表过滤器
  7. Oracle GoldenGate 典型应用场景
  8. java 获取一天零点零分零秒时间戳
  9. 2021-07-05 Ubuntu18安装Caffe-ssd with GPU并运行Apollo mutitask yolo3d
  10. 浅谈设计模式之单例模式