微信的研究及sppeex库的使用(整理)

下面是个人研究微信android 4.2版本的一些结果,不一定正确。

1. 微信android使用的是amr编码;iphone未知,估计是aac,转码会在微信服务器上完成。android上使用了speex这个库,估计是为了达到边录边发。在服务器做格式转换确实比客户端方便多了,用ffmpeg就可以搞定了,也是瘦客户端的一种思路,而且可以依此延伸很多扩展业务。


2. 微信android最新版的数据库依然是sqlite,但文件做了加密,用的是http://sqlcipher.net/


3. 微信发送地理位置用的是google地图,网页地址在assets\map\map_cn.html


4. 微信的视频通信不是在QQ的基础上做的,而是自己实现的一套,基于speex,webrtc, voip等库。微信和QQ的视频通信和skype相差太远了,特别是网络好的情况下。看来视频通信还是有技术壁垒的,现在只能希望Google将webrtc做成熟一点了。


5. 微信使用了一些jni:
    libImgProcess.so 用于gif处理,特别是抠背景。这个微信在一个讲座里面还专门提过。
    libvprotocal.so 用于视频录制,不过这个库效率也不高。录制一分钟的视频,等待压缩要半分钟。干嘛不像Instagram放在后头偷偷去做,或者边做边录。
    libMMProtocalJni.so  用于pcm转amr,不用android系统自带的是因为可以边录边发,这个库也做了插件相关的一些处理
    libvoipMain.so 视频通话
    libvoice.so 视频通话语音处理,用了speex
    libSync.so 用于通讯录同步
    libImgFilter.so 用于图片处理的滤镜
    libmmcrypto.so 数据库加密,其实就是sqlcipher


6.  我原先以为微信会在QQ的基础上做视频通话,但实际上它没有,可能是因为这样可以比较独立,不用遵循QQ的协议。不过QQ的协议为了兼容,有了很重的历史包袱,已不太适合新潮流了。微信的视频通话用了两个服务器:punch.weixin.qq.com和voip.weixin.qq.com。这两个服务器主要是为了打洞和握手。


7. 从http://timyang.net/architecture/notes-weixin/和腾讯大讲堂的一些资料,谈的比较多的是类Sync协议。从张小龙做邮箱的背景来看,我原本以为会是这样一种协议:每个消息相当于一条邮件,而微信的各个界面相当于邮箱的各个文件夹,例如收件箱,发件箱,垃圾邮件,自定义文件夹等,客户端和服务器端要做的就是做这些文件夹同步,就像rsync一样。但从后面的了解来看,实际上并没有这样做。我觉得用邮件来理解IM系统是最直观的方式,发一条消息相当于发一封邮件,邮件体系里面已经很好地做到了转发,分布式,邮件组,邮件状态等功能,客户端要做的就是同步邮件和联系人等。


8. 从微信的发展来看,微信后面应该是朝着平台方向发展,也就是它提供推送和消息发送平台,让其他厂商依此开发应用,发布信息,做活动等。现实中的一句话:要致富,先修路。互联网的路就是互通,就是交流。QQ就是站住了这个先机,所以后面可以做很多其他的事情来赚钱。

speex库的使用

Speex 是近年来开发出的一套功能强大的语音引擎,能够实现高质量和低比特率的编码。它不仅提供了基于码激励线性预测(CELP)算法的编/解码模块,而且在其最新发布的版本中还提供了声音预处理和声学回声消除模块,为保障IP网络中的语音通信质量提供了技术手段。此外,Speex还具有压缩后的比特率低(2~44 kbps)的特点,并支持多种比特率。这些特点使得Speex特别适合VoIP的系统。

虽然是开源的,但是使用的人还不是很多,网上的资料也很少,下面简单给大家介绍一下如何使用speex的API。

一:编码流程

   使用SpeexAPI数对音频数据进行压缩编码要经过如下步骤:

1、      定义一个SpeexBits类型变量bits和一个Speex编码器状态变量enc_state

2、     调用speex_bits_init(&bits)初始化bits

3、    调用speex_encoder_init(&speex_nb_mode)来初始化enc_state。其中speex_nb_modeSpeexMode类型的变量,表示的是窄带模式。还有speex_wb_mode表示宽带模式、speex_uwb_mode表示超宽带模式。

4、    调用函数int speex_encoder_ ctl(void *state, int request, void *ptr)来设定编码器的参数,其中参数state表示编码器的状态;参数request表示要定义的参数类型,如SPEEX_ GET_ FRAME_SIZE表示设置帧大小,SPEEX_ SET_QUALITY表示量化大小,这决定了编码的质量;参数ptr表示要设定的值。

   可通过speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &frame_size) speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &quality)来设定编码器的参数。

5、   初始化完毕后,对每一帧声音作如下处理:调用函数speex_bits_reset(&bits)再次设定SpeexBits,然后调用函数speex_encode(enc_state, input_frame, &bits)参数bits中保存编码后的数据流。

6、      编码结束后,调用函数speex_bits_destroy (&bits)    speex_encoder_destroy (enc_state)

二:解码流程

同样,对已经编码过的音频数据进行解码要经过以下步骤:

1、      定义一个SpeexBits类型变量bits和一个Speex编码状态变量enc_state

2、    调用speex_bits_init(&bits)初始化bits

3、    调用speex_decoder_init (&speex_nb_mode)来初始化enc_state

4、     调用函数speex_decoder_ctl (void *state, int request, void *ptr)来设定编码器的参数。

5、    调用函数 speex_decode(void *state, SpeexBits *bits, float *out)对参数bits中的音频数据进行解编码,参数out中保存解码后的数据流。

6、    调用函数speex_bits_destroy(&bits), speex_ decoder_ destroy (void *state)来关闭和销毁SpeexBits和解码器。

下面是一段实例代码:

转载请注明:http://hi.baidu.com/a�dz�����a/

#include <speex.h>

#include <stdio.h>

 

#define FRAME_SIZE 160

int main(int argc, char **argv)

{

char *inFile;

FILE *fin;

short in[FRAME_SIZE];

float input[FRAME_SIZE];

char cbits[200];

int nbBytes;

 

void *state;

 

SpeexBits bits;

int i, tmp;

//新建一个新的编码状态在窄宽(narrowband)模式下

state = speex_encoder_init(&speex_nb_mode);

//设置质量为8(15kbps)

tmp=8;

speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);

inFile = argv[1];

fin = fopen(inFile, "r");

//初始化结构使他们保存数据

speex_bits_init(&bits);

while (1)

{

//读入一帧16bits的声音

fread(in, sizeof(short), FRAME_SIZE, fin);

if (feof(fin))

break;

//把16bits的值转化为float,以便speex库可以在上面工作

for (i=0;i<FRAME_SIZE;i++)

input[i]=in[i];

//清空这个结构体里所有的字节,以便我们可以编码一个新的帧

speex_bits_reset(&bits);

//对帧进行编码

speex_encode(state, input, &bits);

//把bits拷贝到一个利用写出的char型数组

nbBytes = speex_bits_write(&bits, cbits, 200);

//首先写出帧的大小,这是sampledec文件需要的一个值,但是你的应用程序中可能不一样

fwrite(&nbBytes, sizeof(int), 1, stdout);

//写出压缩后的数组

fwrite(cbits, 1, nbBytes, stdout);

}

//释放编码器状态量

speex_encoder_destroy(state);

//释放bit_packing结构

speex_bits_destroy(&bits);

fclose(fin);

return 0;


}


 

你可能感兴趣的:(微信的研究及sppeex库的使用(整理))