3

此处输入图片的描述

自己挖的坑,果然要自己填!

由于之前开启了CRSF,想增强安全性。过了一段时间,自己吧这事给忘了,导致JS的ajax消息无法发送到后台,一直提示400 BAD request。找了好久才发现,详情

但是也找到个可以检测并且建议的办法,ajax提供error反馈错误信息。

$.ajax({
    url: "/profile/{{ user_id }}",
    type: 'POST',
    data: {data: "failed"},
    error: function(e) { //增加错误反馈
        console.log(e);
    }
})
.done(function (data) {
    console.log(data);
});

前后端交互

  • 访问个人主页(wx_config)

  • 微信上传语音

  • 传递mediaId和record_time到后台

  • 获取token从微信下载语音

  • 上传语音到qiniu(发起任务转换amr为mp3)

  • 存储url+time到数据库

下载语音

获取token和ticket

说明一下:两处需要用到access_token,一是在微信账号绑定的域名下使用JS-SDK上传文件时,通过token来生成ticket来初始化JS-SDK;二是在下载文件时需要认证号产生的token。

本以为JS-SDK的可以使用未认证账号来产生access_token从而产生ticket用于JS端上传数据,从而避免出现提示“XXXX”需要使用录音功能。但是下载时发现,微信会校验mediaId是否来自同一个公众号(不校验才怪勒)。所以上传和下载必须使用同一个已认证微信公众号的APPID和APPSECRET来产生token。

两个不同的服务器都需要token和ticket,为了避免抢走导致一方失效。一个服务器产生token和ticket存于缓存中,每小时更新一次(微信限制每天不超过2000次),并提供其他服务器获取token和ticket的接口。其他服务器需要使用直接通过接口获取即可。

录音时间

录音时间不需要单独存储,直接存储在audio的链接中,通过锚点的方式
http://7xogxw.com1.z0.glb.clouddn.com/2015-11-26 23:11:06.709113#time23
每次读取audio_url,先分割获取录音时间,url和time分别传到前端渲染。

真正的自适应:关于图片,以后可以通过类似的方式,用锚点记录图片的实际长宽,而在前端加载之前,通过url即可获取长宽数据,从而根据设备实际分辨率,折算合适长宽并发起请求,减少大图加载缓慢。同时可以在图片加载之前就可以生成固定比例的图片占位符,避免加载过程中出现页面跳动。

上传语音

上传文件

之前已经实现过七牛图片的上传,但是当初的接口复杂难用(@Lee 佩服),想着要修改之前的上传接口来上传语音文件,我决定还是使用最新qiniu-sdk来上传文件,之前图床是用到过,使用简洁了很多。

但是一个麻烦的问题,新版本的sdk向下兼容性不是很好,如果使用最新的,之前的会报错,具体不知。而要去修改之前的接口和上传部分代码,工作量太大,于是两个版本sdk同时使用,导入新的包为qiniu2,修改所有引用qiniu位置为qiniu2,OK,一切正常。

一般情况,直接获取token上传数据,相当简单。

import qiniu2
from datetime import datetime
import config
from qiniu2 import BucketManager
import base64

def get_token():
    q = qiniu.Auth(config.QINIU_ACCESS_KEY, config.QINIU_SECRET_KEY)
    token = q.upload_token(config.PIC_BUCKET)
    return token
    
up_token, key = upload.get_token()
ret, info = qiniu2.put_data(up_token, key, resp)
assert ret['key'] == key

格式转换

而微信默认amr格式,html不支持。上传语音需要预处理,需要policy用于存储转换的格式、另存到位置和名称等信息来产生up_token。并且如果policy和put_data中的key相同且bucket相同,即可同名覆盖,减少空间使用。

这一段单独看七牛的文档你是啥也看不到的,只告诉你预处理格式。segmentfault上有七牛程序员入驻,可查到很多东西

def get_token():
    q = qiniu2.Auth(config.QN_ACCESS_KEY, config.QN_SECRET_KEY)
    # 文件名称
    key = str(datetime.now())
    # 转换格式
    format = "avthumb/ogg"
    # 另存到bucket和对应名称key
    entry_uri = config.AUDIO_BUCKET + ':' + key
    entry_uri = "saveas/"+ base64.urlsafe_b64encode(entry_uri)
    # 独立队列audioQueue转换
    policy = {
        "persistentOps": format + "|" + entry_uri,
        "persistentPipeline": "audioQueue"
    }
    token = q.upload_token(config.AUDIO_BUCKET, policy=policy)
    return token, key

up_token, key = upload.get_token()
ret, info = qiniu2.put_data(up_token, key, resp)
assert ret['key'] == key

删除文件

上传新的语音的时候,需要删除原来的语音文件。同样很简单,提供需要删除的问题件的key即可。

def del_file(upkey):
    q = qiniu2.Auth(config.QN_ACCESS_KEY, config.QN_SECRET_KEY)
    bucket = BucketManager(q)
    ret, info = bucket.delete(config.AUDIO_BUCKET, upkey)
    return ret, info

语音播放

兼容格式

一开始看html的audio标签的时候,默认ogg和mp3均可。所以默认转换为ogg。最后iOS上不无法播放,于是检查发现iOS压根就不兼容ogg格式,最终转换为mp3格式。

  • iOS录音PC能播放,不是前端、后台原因。

  • 确定iOS的微信兼容audio
    全民K哥能播放,全民K哥的js判断支持h5则使用audio否则flash,而微信支持h5。通过canPlayType属性即可检测。

  • 测试audio兼容性(如果最早就加入并进行检测,前面的都不用折腾)

// 检测能否兼容audio
function support_audio(){
    return !!document.createElement('audio').canPlayType;
}
// 检测能否兼容ogg
function support_audio_ogg(){
    var elem = document.createElement('audio');
    return elem.canPlayType('audio/ogg; codecs="vorbis"');
}
// 检测能否兼容mp3
function support_audio_mp3(){
    var elem = document.createElement('audio');
    return elem.canPlayType('audio/mpeg;');
}

console.log('audio:' + support_audio());
console.log('audio-ogg:'+ support_audio_ogg());
console.log('audio-mp3:'+ support_audio_mp3());

参考:http://www.vnadd.com/25160.htm

  • 使用jsconsole远程调试
    通过该工具可以远程查看访问机器输出到console的数据,即可知道是否兼容。

【总结】感觉还是晚起比较好,整天都有状态,11点起来,吃了个饭,然后一直写到晚上12点,以上绝大部分都是这期间完成的,中间吃了个晚饭。原因:牛津大学教授:早睡早起是错误观念,其实我就是想给睡懒觉找借口。

原文链接


SkyWay
554 声望10 粉丝

Coding changes the world!


引用和评论

0 条评论