感觉记忆力不行了,才做了就有点忘了.先简单做下记录...

遇到的问题

  • 需要类似微信的语音发送功能
  • 前端发送给后端,在mogodb中用二进制存储.后端取到数据发送给我的也是blob.前端拿到数据就变了.
  • layim列表和聊天面板改写





解决方法

** 以微信语音发送的方式处理语音发送**

在layim手机版本中没有语音发送的具体接口,但是存在一个扩展tool(),layim的pc端发送语音是直接发送一个线上url.但是这里需要使用手机录音.

接下来是使用手机录音

在layim的聊天模板中新增一个隐藏按钮,用于自定义手机的touch事件.

监听layim的一个扩展

layim.on('tool(audio)', function(insert, send) {
$("#recordBtn").toggleClass('on'); // 点击显示隐藏录音按钮
});

layim-mobile.js内部自定义了一个监听,以便在外部获取到录音按钮

// 自定义一个监听
var wch_listener = function() {
wch_event = new CustomEvent('wch_listener', {
detail:{
name: 'wch',
audioBtn: othis.parents('.layui-m-layer').siblings('.layui-m-layer').find('#recordBtn'),
sendAudio: sendAudio // 发送消息的函数
}
});
window.dispatchEvent(wch_event); // 显式触发
}

监听录音

//监听自定义工具栏--录音的点击
window.addEventListener('wch_listener', function(event) {
// 如果是CustomEvent,传入的数据在event.detail中
if (navigator.mediaDevices.getUserMedia) {
console.log('getUserMedia supported.');
var constraints = {
audio: true
};
var chunks = [];
var onSuccess = function(stream) {
var mediaRecorder = new MediaRecorder(stream),
to = '',
recordStartTime = '',
recordendTime = '',
startY, endY,
recordedTime = 0,
interval; event.detail.audioBtn.on({
touchstart: function(e) {
var othis = this;
to = JSON.parse(decodeURIComponent($(this).parents('.layim-chat-send').siblings('.layim-chat-tool').data('json')));
mediaRecorder.start();
startY = e.touches[0].pageY;
$(othis).html('0S, '+i18n.t('m.chat_0042')) // 松开发送
interval = setInterval(function() {
recordedTime++;
$(othis).html(recordedTime + 'S, '+i18n.t('m.chat_0042')) // 松开发送
if(recordedTime >= 20) {
clearInterval(interval);
mediaRecorder.stop();
$(this).html(i18n.t('m.chat_0041')) // 按住录音
console.log("recorder stopped");
}
}, 1000)
recordStartTime = new Date().getTime();
console.log("recorder started");
},
touchmove: function(e) {
if(e.changedTouches[0].pageY- startY >= 100 || e.changedTouches[0].pageY - startY <= -100){
endY = e.changedTouches[0].pageY;
clearInterval(interval);
if(mediaRecorder.state === 'recording') {
mediaRecorder.stop();
}
$(this).html(i18n.t('m.chat_0041')) // 按住录音
recordendTime = new Date().getTime();
console.log("recorder stopped");
}
},
touchend: function(e) {
if(mediaRecorder.state === 'recording') {
endY = e.changedTouches[0].pageY;
mediaRecorder.stop();
$(this).html(i18n.t('m.chat_0041')) // 按住录音
recordendTime = new Date().getTime();
console.log("recorder stopped");
}
}
})
mediaRecorder.onstop = function(e) {
recordedTime = 0;
clearInterval(interval);
if (endY - startY >= 100 || endY - startY <= -100) { // 取消发送
// 重置录音数据
chunks = [];
} else {
// 保存录音
var blob = new Blob(chunks, {
'type': 'audio/mp3'
}),
center_info = JSON.parse(localStorage.getItem('account_info')),
project_info = JSON.parse(localStorage.getItem('project_basic'));
// 发送录音
let audioPara = {
touserid: to.id , // to.gid ,
username: center_info.user_name,
avatar: layui.cache.dir + 'images/face/' + (Math.random() * 72 | 0) + '.gif',
type: 'friend',
content: blob,
cid: '',
mine: false,
userid: project_info.db + center_info.user_guid,
project_id:project_info.db
};
var fr = new FileReader ()
fr.readAsDataURL(blob, {type: 'audio/mp3'})
fr.onload = function(e) {
var audioEle = document.createElement('audio')
audioEle.src = e.target.result;
event.detail.audioBtn.after(audioEle)
} console.log(audioPara)
event.detail.sendAudio(socket, audioPara)
// socket.emit('sendAudioMessage', audioPara)
// that.displayAudio(blob, true, event.detail.audioBtn)
// 重置录音数据
chunks = [];
}
} // 录音逻辑
mediaRecorder.ondataavailable = function(e) {
chunks.push(e.data);
}
}
})

// 监听录音发送

 //发送语音
var sendAudio = function(socket, audioPara){
var data = {
username: cache.mine ? cache.mine.username : i18n.t('m.chat_0022')
,avatar: cache.mine ? cache.mine.avatar : (layui.cache.dir+'css/pc/layim/skin/logo.jpg')
,id: cache.mine ? cache.mine.id : null
,mine: true
};
var thatChat = thisChat(), ul = thatChat.elem.find('.layim-chat-main ul');
var To = thatChat.data, maxLength = cache.base.maxLength || 3000;
var time = new Date().getTime(), textarea = thatChat.textarea;
// 使用objectURL做src,失败->416错误
// let blob = new Blob([new Int8Array(audioPara.content)], {type: 'audio/mp3'});
// let src = URL.createObjectURL(blob);
// 使用base64作src
var fr = new FileReader();
fr.readAsDataURL(audioPara.content);
fr.onload = function(e) {
data.content = e.target.result;
if(data.content === '') return;
if(time - (sendMessage.time||0) > 60*1000){
ul.append('<li class="layim-chat-system"><span>'+ layui.data.date() +'</span></li>');
sendMessage.time = time;
}
console.log(data)
ul.append(laytpl(elemChatAudio).render(data)); var param = {
mine: data
,to: To
}, message = {
username: param.mine.username
,avatar: param.mine.avatar
,id: To.id
,type: To.type
,content: param.mine.content
,timestamp: time
,mine: true,
dataType: 'audio'
};
pushChatlog(message);
console.log(audioPara)
socket.emit('sendAudioMessage', audioPara)
To.content = data.content;
To.dataType = 'audio';
setHistory(To);
chatListMore();
textarea.val(''); textarea.next().addClass('layui-disabled');
}
};

layim-mobile.js中新增一个展示语音聊天的模块

  var elemChatAudio = ['<li class="layim-chat-li{{ d.mine ? " layim-chat-mine" : "" }}">'
,'<div class="layim-chat-user"><img src="{{ d.avatar }}"><cite>'
,'{{ d.username|| i18n.t("m.chat_0008") }}'
,'</cite></div>'
,'<div class="layim-chat-text"><div class="layui-unselect layui-layim-audio" layim-event="playAudio" data-src="'
,'{{ d.content }}'
,'"><i class="layui-icon"></i><p>音频文件</p></div></div>'
,'</li>'].join('');

至于后端传给我是blob结果拿到却不是的问题

这个应该是在websocket传输的过程中转码了,不是太清楚.刚开始没有弄明白自己拿到的是什么格式(类型)的数据,后面看了下自己转成base64的文件,有点像诶.好吧试着转一下

var bString = atob(item.content); // 结果证明,从数据库中拿到的的确是没有编码头的base64的数据,或者叫(ASCII码数据)
var len = bString.length;
var arr = new Uint8Array(len);
while(len--){
arr[len] = bString.charCodeAt(len);
}
var blob = new Blob([new Int8Array(arr)], {type: 'audio/mp3'});
var src = URL.createObjectURL(blob);
item.content = src
ul.append(laytpl(elemChatAudio).render(item));

看着这些代码,脑袋晕,还是自己太撇火药了,哪天想起了看看能不能再来整理下吧

layim手机版嵌入app的更多相关文章

  1. 手机版WEB开发经验分享,手机版网站开发注意事项,网站自适应,手机版网站自适应,移动安卓APP自适应

    转自 http://my.oschina.net/cart/blog/282477 做前端开发不短了,用过jQuery Mobile jqMobi 也纯手工写过.. 最后总结如下: jQuery Mo ...

  2. 一起学微软Power BI系列-使用技巧(3)Power BI安卓手机版安装与体验

    Power BI有手机版,目前支持安卓,苹果和WP,不过没有WP手机,苹果在国内还不能用,要FQ和用就不测试了.安卓的我也也是费了九牛二虎之力才把app下载下来,把方法分享给大家. FQ太麻烦,所以建 ...

  3. 手机网页唤醒app,

    1.在系统系统自带的浏览器中 首先做成HTML的页面,页面内容格式如下: <a href="[scheme]://[host]/[path]?[query]">启动应用 ...

  4. 手机号码生成器app有吗,怎么使用的呢?

    手机号码生成器app是有的,他有手机号码生成器安卓版,也有手机号码生成器苹果版的.很多人会误解他的功能以为是拿来生成号码来接验证码的,其实他不是拿来接短信的.它是用来给别人做营销找客沪的找客源的,接不 ...

  5. 鸿蒙手机版JNI实战(JNI开发、SO库生成、SO库使用)

    鸿蒙JNI开发现状 现阶段,不仅鸿蒙JNI相关的开发资料较少,而且Phone相关的JNI开发资料几乎没有,这对于新入行的鸿蒙开发者们来说,非常不友好. 也可能会给Android工程(使用了SO库的工程 ...

  6. discuz手机版模板开发

    1.触屏版模板手机路径 discuz X3触屏版模板路径:/template/default/touch/forum/discuz.htm(主页面模板) discuz X3标准版模板路径:/templ ...

  7. 微信小视频复制到手机本地Android APP 分享

    因为需要将拍的宝宝的微信小视频上传到亲宝宝软件,每次去手动找文件比较麻烦,所以做了个微信视频复制到手机本地的APP,做工虽然粗糙,但是绝对实用, 下载地址 http://pan.baidu.com/s ...

  8. phpcms v9 黄页实现手机访问手机版,电脑访问电脑版(双模板)

    第一步.模板文件夹下,yp复制一份,改名字 ypwap 第二步.修改phpcms/modules/yp/index.php和phpcms/modules/ypwap/index.php //判断客户端 ...

  9. php 判断是手机版还是电脑端

    function isMobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset ($_SERVER['HTTP_X_WAP_PROFILE'])) { ...

随机推荐

  1. volatile变量能保证线程安全性吗?为什么?

    在谈及线程安全时,常会说到一个变量——volatile.在<Java并发编程实战>一书中是这么定义volatile的——Java语言提供了一种稍弱的同步机制,即volatile变量,用来确 ...

  2. 使用shiro做权限管理的学习笔记整理

    Shiro权限管理 参考:https://www.cnblogs.com/jpfss/p/8352031.html Shiro解决的问题 授权和鉴别的问题:Authenrization(授权) Aut ...

  3. vue使用talkIngData统计

    上篇刚使用了百度统计,由于后端同事没有找到百度统计的api,于是就找了个talkingData平台... 平台地址 依旧是先注册 进入应用统计分析  创建应用 获得appid 在vue中埋点 1.in ...

  4. 【Linux系列】Centos 7安装 Nginx(三)

    目的 为了下面的Laravel部署,本篇开始安装Nignx服务器. 防火墙设置 在物理主机上查看nginx是否安装成功,需要开放虚拟机的80端口. 用cmder登录到虚拟机 firewall-cmd ...

  5. 【NHOI2018】找素数

    [题目描述] 素数又称质数,是指一个大于 1 的正整数,如果除了 1 和它本身以外,不能再被其它的数整除,例如:2.3.5.97 等都是素数.2 是最小的素数. 现在,给你 n 个数字,请你从中选取一 ...

  6. JavaScript笔记十

    1.正则表达式 - 语法: - 量词 {n} 正好n次 {m,n} m-n次 {m,} 至少m次 + 至少1次 {1,} ? 0次或1次 {0,1} * 0次或多次 {0,} - 转义字符 \ 在正则 ...

  7. Java基础IO类之字节输入输出流

    一.IO流概述 1.IO流:输入输出流(Input/Output) 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象,即数据在设备间的传输流, 流的本质是数据传输,根据数据传输特性将 ...

  8. CSS中如果实现元素浮动,看这篇文章就足够了

    浮动基本介绍 在标准文档流中元素分为2种,块级元素和行内元素,如果想让一些元素既要有块级元素的特点也同时保留行内元素特点,只能让这些元素脱离标准文档流即可. 浮动可以让元素脱离标准文档流,可以实现让多 ...

  9. 【python测试开发栈】—python内存管理机制(二)—垃圾回收

    在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...

  10. 不要再造轮子了:聊一聊 JavaScript 的 URL 对象是什么?

    本文由葡萄城技术团队于博客园翻译并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 如果我们自己编写从URL中分析和提取元素的代码,那么有可能会比较痛苦 ...