mongodb
基于分布式文件存储,非关系数据库,类似json的bson格式
http://www.mongodb.org/downloads
mongo 10.50.141.25/nuvedb // 用IP连接某个数据库 mongo --port 27017
show dbs // 显示所有数据库
use nuvedb // 进入某个数据库
show collections // 显示此数据库的所有表
db.records.find().count() // 显示某表的所有记录的数目
db.records.find({"state":{$gt:4}}, {filename:true}) //查询状态大于4的且只显示文件名
db.records.distinct("state") // [ 5, 3, 4, -1 ] 显示状态列且不重复
db.records.update({filename:/c71129a/},{$inc:{"state":1}},false,true) // 条件,设置加1,插入否,多条更新是
db.records.remove({state:4}) // 删除记录
db.records.drop() // 删除表
服务器端:
mongod --dbpath ./testMongo/master/ --port 10000 --master --logpath ./masterlog.txt --logappend // 启动主服务器
echo ''>./masterlog.txt // 服务器运行时,清空后继续写日志;删除日志文件后,后续的就写不了
mongod --dbpath ./testMongo/slave/ --source 10.50.141.43:10000 --slave --port 10001 --logpath ./testMongo/slave/mylog/slave.log // 启动从服务器,带log
mongodump -h 10.50.141.43:10001 -d masterDing -o ./testMongo/slave/mydump/ // 备份哪个服务的什么库到什么地方
mongorestore -h 10.50.141.43:27017 --directoryperdb ./testMongo/slave/mydump/ // 恢复到哪个服务,用什么数据
部署:主从,副本集,分片
副本集就是有自动故障恢复功能的主从集群。
问题:
1. 快:空间换时间,加载到内存的数据不会主动释放(索引,命中的数据块),多了导致宕机
2. 数据量过万,不稳定
3. collections层的删除,并没有直接释放空间,长期导致大量碎片,如下
当在mongodb中删除了大量的数据后, 日志中会出现以下信息:
[conn154] info DFM::findAll(): extent 2:8c6c000 was empty, skipping ahead. ns:eu3g.rankings_general
意思是太多闲置的空间(删除体积较大的集合,或删除大量文档后腾出的空间)。
可以通过修复命令来压缩数据: db.repairDatabase();
socket
WebSocket
是一个基于TCP的协议,就是握手链接的时候跟HTTP相关(发了一个HTTP请求),这个请求被Server切换到(Upgrade)websocket协议了。
websocket把 80 端口作为默认websocket连接端口,而websocket的运行使用的是443端口。它是实现了浏览器与服务器的全双工信息传输。经过简单的握手协议,建立一个长连接,按照协议的规则进行数据的传输。
socket.io
// 建立socket
服务器:var io = require("socket.io").listen(5000);
io.sockets.on("connection", function(socket){
socket.on("initconnection", function(data, callback) {
}) });
客户端:var socket = io.connect(url);
socket.emit("initconnection", {say:'h r u?', user:'dld'}, function(res) {
});
//中转消息 : clientA:emit("A")--->Server--->clientB:on("B")
服务器: socket.on("A", function(data, callback){
io.sockets.socket(socketId).emit("B", data);
});
design
基于WebRTC实现的: 网页实时通信(Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的技术,是谷歌2010年收购的。
one2Many 把多对多的通信,分解为每个点对应的一个one2Many结构。 MCU分配: 原则,尽量避免跨MCU,减小碎片。方法,排序后把数目最接近的进行分配。 log:log文件太大,会影响系统的运行。log分级,分模块,加时间。 void log(enum PrintLevel level, const char* _format, ...); #define INFO_LOG(format,args...) _log.log(INFO_LOG, format, ##args) wiucs::Testlog _log; // 每个使用打印的类定义一个这样的成员变量
利用amqp来完成rpc(远程过程调用,即通过网络从远程计算机程序上请求服务)
erizoController.js -----{client}--rpc(amqp)-{server}-----nuve(管理多个eCtrl)
\----------------{server}--socket.io/websocket--{client}----client.js
工具
js打包工具compiler.jar // java -jar compiler.jar --js xxx.js
node-GYP 项目构建工具
node_addon node调用Linux下的动态库,库由c++实现。
需要node内部的库,比如ObjectWrap, Node已将所有依赖关系静态地编译成可执行文件,因此我们在编译自己的组件时不需要担心和这些类库的链接问题。
rabbit amqp(高级消息队列协议)
生产者 ----- eXchange ---'routeKey1'--->Queue1-----消费者1
|----'routeKey2'--->Queue2-----消费者2
1. 连接rabbitServer, 创建交换机,队列,将他们之间用关键字关联起来。
交换机:var exc =conn.exchange(Xname, option, cb);
队列:var q = conn.queue(Qname,cb);
绑定:q.bind(Xname, routeKey);
2. 队列1(nuve): 存放被别人调用的一些函数,取出执行并将结果存放到队列2。
如何存放:生产者为其调用者如:ec调用 callRpc = function (routeKey, method, args, callback)
实际处理为: var send = {method: method, args: args, corrID: corrID, replyTo: clientQueue.name
exec.publish(routeKey, send)
执行并处理结果:q.subscribe(function (message) {
rpcPublic[message.method](message.args, function (result) {
exc.publish(message.replyTo, {data: result, corrID: message.corrID});
});});
3. 队列2(clientQ):存放的是队列1执行的结果,将结果作为参数用回调函数处理
通过replyTo收到结果,通过corrID调用callback来处理: map[message.corrID].fn(message.data);
4. 多个不同的处理进程,可以在此进程注册后,再绑定相应的处理队列
如ec的处理:在注册到nuve后(ec[i] = {...}),再生成q = conn.queue(ec_id, cb);
keepAlive
server: nuve定时给每个mcu的keepAlive +1
checkKAInterval = setInterval(checkKA, INTERVAL_TIME_CHECK_KA); // cloudHandler.js
checkKA = function() {...erizoControllers[ec].keepAlive += 1;...} // cloudHandler.js
client: mcu把nuve上面对应自己的设置为0
rpc.callRpc('nuve', 'keepAlive', myId, callback); //ec.js
keepAlive = function (id, callback) {... erizoControllers[id].keepAlive = 0; ...} // cloudHandler.js
event
1. 增加监听(注册函数) addEventListen(type, listen); // eventListeners[eventType].push(listener);
2. 派遣(调用函数) dispatchEvent(event); // 调用 eventListeners[event.type][listener](event);
js
// 数组
var arr = [];
arr.push(1);
arr.splice(index, count);
// 模块导出
var wiucs = wiucs || {}; // wiucs.ex = ( function (wiucs) { return {}; } (wiucs) ); // 使用 wiucs.ex.returnSomeValue module.exports = wiucs;
函数定义后执行 (function(){})();
函数调用并后台执行: ( run; ) &
捕捉信号并处理: trap "exit_fun" 2 3 9 15
多个条件并列: while [ $LENGTH -gt $INDEX -a "$EXIT_NOW" = "0" ]; // -a == and ?
结构以及数组 var rooms = {};
rooms[roomid] = {};
rooms[roomid][ecid] = {streams:{}, sockets:{}}; // 结构带有标签
rooms{roomid][ecid].streams[streamid] = {aSsrc:,...};
nodejs及其组件的功能
// 单线程而并发操作:Node.js事件轮询机制(event loop)
创建webApp
var express = require("express");
var app = express();
// 创建webServer
var http = require("http");
var server = http.createServer(app);
server.listen(8000);
// 处理文件
var fs = require("fs");
// 执行linux 命令
var exec = require("child_process").exec;
exec(execStr, function(err, output){});
//XMLhttprequest发送请求
var req = new XMLHttpRequest();
req.onreadystatechange = function() { if (req.readystate == 4) callback(req.responseText);}
HTML杂项
iframe/window之间的信息传递
假设从A传递到B:
A:window.parent.BframeName.postMessage(message, "*");
B : window.attachEvent("onmessage", callbackFunc); // or addEventListener("message", func, false)
var callbackFunc = function(e) { var data = e.data;}
div中显示可缩放矢量图形(Scalable Vector Graphics,SVG)
document.getElementById("divId").innerHTML = "
chrome
navigator.getUserMedia({
video: {
mandatory: {
minHeight:600,
maxBandwidth:500
},
optional: [
{
maxAspectratio: 1.333333333333,
minTimebetweenrefframes: 20,
minFramerate: 30,
enumAutowhitebalance: "on"
},
{
minTimebetweenrefframes: 40,
minFramerate: 10
},
]
}
});
lib
ffmepg, libvpx
libwebm: 修改webm参数: 1440 *900; 25fms
media
PCM(Pulse-code modulation),即脉冲编码调制
放MP3,要把数据解压还原成最简单的原始数据才行。
waveXXX底层函数操作的都是pcm数据,也就是wave数据,也就是我们在音频里常说的原始数据。
MP3之类的是压缩过的数据,要让声卡放MP3,必须把MP3翻译(解压缩)成声卡认识的数据格式。声卡一般只认一种格式,就是wave那种原始的裸数据
相关
每个采样点都记录下了原始模拟声波在某一时刻的状态,通常称之为样本(sample)
而每一秒钟所采样的数目则称为采样频率
对于采样过程中的每一个样本来说,数字音频系统会分配一定存储位来记录声波的振幅,一般称之为采样分辩率或者采样精度
采样就是每隔一定时间就读一次声音信号的幅度,而量化则是将采样得到的声音信号幅度转换为数字值
奈奎斯特(Harry Nyquist)采样理论:如果对某一模拟信号进行采样,则采样后可还原的最高信号频率只有采样频率的一半,
或者说只要采样频率高于输入信号最高频率的两倍,就能从采样信号系列重构原始信号。
帧率:Frames per Second,简:FPS。(30fps感受可以,60fps完美,75fps感受不到更好的差异。
屏幕的刷新频率一定要大于帧率,否则浪费帧!)
YUV帧: 「Y」表示明亮度(Luminance、Luma),「U」和「V」則是色度、濃度(Chrominance、Chroma),
采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。
如果用directx,是直接获得YUV数据. 如果是用api,则是位图,还得再转成YUV才能进行视频压缩.
cng是产生一段背景静音
Vorbis : 免费,多声道,流式,可变编码速率,音频编码
PCMA == G.711A 64kbps 宽带(低带宽: G723需要5.3/6.4kbps,G729需要8kbps)
音频 ISAC : 16000采样率, 16 bits采样精度, 1 channel通道
rtpHead.csrc * 4 ? // csrc列表个数 * 每项4个字节
mkv :多种格式的音视频,多音轨,带字幕
录完了都要用视频编辑软件再编码压缩的...
我当初录游戏1680X1050分辨率的40分钟总共30G 压完了是1G的AVI X264编码 1440X900
音视频同步
由开始记录的,第一个audio/video的rtp/rtcp包,得到第一个A,V rtp包的时间戳pts,单位纳秒 (1秒 == 1000 000 000 纳秒)
1) 有音频的rtp, rtcp包的时间戳的差值 / 采样频率 = 两包的时间差(秒),
rtcp中有ntp,即64bit的标准时间(纳秒),从而可以得到音频的rtp包的时间(纳秒)
2) 音视频rtp包的时间之差,设置为大的pts时间,小的pts时间为0,将pts传入libwebm/ffmpeg的打包中,即可实现同步。
视频帧: I帧:关键帧,P帧:猜测帧,B帧:双向帧
PTS 显示时间戳:是presentaion time stamp,是该包第一个音频采样的时间.
DTS 解码时间戳
混音:
解压缩完之后是PCM, 进行叠加,overflow处理, 然后再压缩,发送.解压之后的PCM的采样率及精度是需要一致的.
直接将PCM的数据做加法,但要注意数据范围,如
8bit音量范围是0-255 , 8bit的相加的结果用short保存
16bit音量范围是-32767-32767 , 16bit的相加结果用int保存,否则你的判断可能是无效的
1,各个声源的采样率一定要一致,不一致的话就要重采样,使之采样率相等。
2,你要确定,你那16BIT到底是不是肯定为一个声音通道的。否则当然不能囫囵吞枣的加起来。
3,其次,检查你的运算代码的运算模式:一定要用浮点数进行计算,哪怕最后再转成整型也成。
4,最次是一些杂项问题,比如Big-ending和Little-ending问题等。
html的video标签支持3中文件格式:
webm = vp8(just move off rtp/vp8 head) +vorbis(isac-->pcm-->vorbis)
mpeg4 = H.264 + aac
ogg = Theora 视频编码 + vorbis 音频编码
libwebm = segment + clusters(= audio track + video track + block)
webRtc中音频的处理流程
采集---〉ISAC编码---〉发送---〉接受---〉ISAC解码---〉播放
|--->rtp记录--->ISAC解码--->vorbis编码--->webm打包---> webm, vorbis解码后播放
计算
音频帧的播放时间 = 一个帧对应的采样样本的个数 / 采样频率
一个AAC原始帧包含一段时间内1024个采样及相关数据,采样率 Samplerate 44100Hz
当前AAC一帧的播放时间是 = 1024个 * 1000ms / 44100个= 22.32(单位为ms)
时间戳 = 每个包/帧的时间 * 采样频率
MPEG,每帧20ms,采样频率8000Hz,设定时间戳单位1/8000,而每个包之间就是 160 = (20ms * 8000个/1000ms)的增量。
130万的摄像头对应多少带宽?
130万像素的网络摄像机,其传输带宽大约需要1Mbps的带宽: 130万比特 * 25帧/秒 / 1024 /1024 / 30压缩比 = 1.03 Mb每秒
40万的?至少分辨率需要480 * 640
480 * 640 * 25 / 1024 / 30 = 250 Kb // 实验数据也是200多Kb
实验数据:
45分钟的屏幕录制:109MB; 20m: 44MB
音频 m=audio 33085 RTP/SAVPF 103 104 0 8 106 105 13 126
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000 // 静音
a=rtpmap:126 telephone-event/8000
视频 m=video 33085 RTP/SAVPF 100 101 102
a=rtpmap:100 VP8/90000
a=rtpmap:101 red/90000
a=rtpmap:102 ulpfec/90000
视频格式
D1 :720 * 480(水平)。480i,隔行扫描。模拟电视水平
D4: 1280*720=921600像素. 720p,逐行扫描。高清,720P(100万像素)
1920*1080=2073600 这是1080p
性能测试工具
CPU,内存:linux下比top好用的系统监视器htop
TCP,UDP:iperf for Linux 的安装与使用
开发
linux: #include ; -lasound -lm ; snd_pcm_open(...) //alsa free and oss not,播放PCM数据
http://www.233.com/linux/fudao/20100122/091957660.html
linux音频编程,基本概念,系统调用open(/dev/dsp,mix...),read(录制),write(播放),close,ioctl(设置参数)...
http://www.rosoo.net/a/201010/10357.html linux alsa 录音,播放,实例解析
window : waveOutWrite(...) // 传入采样频率, 采样精度,通道数,以及PCM数据后,生成wave后播放
2。用svg-editor 实现画图(老师画给学生看)
1。老师客户端:svg-editor.html 用setinterval实现每2秒用xmlhttprequest发送{roomid, svgStr}到服务器nodejs (控制发送完毕后才能再次发送!!!)
iframe得到父窗口的数据:roomid
2。nodejs收到字串后用fs.writeFile保存为文件roomname.svg
3。学生客户端在图画tab为可见时,每2秒刷新图画所在的iframe: draw.location.reload()
3。用express实现文件上传 1. 客户端
// 此代码直接隐式得将form中的file, post到/file-upload; 或者 用XMLHttpRequest显示的post,并且添加了progress等事件监听
2. 服务器端用nodejs的expressJS支持实现app.post('/file-upload', function(req, res) {
// 注意:上传的临时路径为:/tmp/XXXXXXXXX, 文件名为随机字串 var tmp_path = req.files.thumbnail.path;
var target_path = './xxx/' + req.files.thumbnail.name;
// 文件重命名,并删除临时文件
fs.rename(tmp_path, target_path, function(err) {
if (err) throw err;
fs.unlink(tmp_path, function() {
if (err) throw err;
res.send('File uploaded - ' + req.files.thumbnail.size + ' bytes'); }); }); });
6。将pptx转化为html1. 下载openoffice or libreoffice(ubuntu 12.04自带), jodconvert
2. 在后台运行office,并监听 (将运行命令写成脚本.sh)
3. 调用jodconvert进行文档转换: java -jar .../jodconvert...jar old.pptx htmldir/new.html
注意;用chmod修改权限; 生成html文件存放的目录
NPAPI(Netscape Plugin Application Programming Interface,网景插件应用程序接口)GetEntryPoints, Initialize, Shutdownnptypes.h : NPAPI 的变量类型定义npapi.h : NPAPI 定义插件的接口函数说明和常用结构说明npruntime.h : 插件与JavaScript交互的结构说明 npfunctions.h : 调用浏览器的接口函数和结构
client widget:
$.fn.wiucsST=function(){
var s; // 存储初始化参数
var methods={
init:function(p){
var o = $(this); // 表示当前文档
s = $.extend( {
room: null,
user: null
}, p );
o.append();
// s.room.getId()
},
destory:function(){
}
}; // methods end
var method = arguments[0];
if(methods[method]) {
method = methods[method];
arguments = Array.prototype.slice.call( arguments, 1);
} else if( typeof(method) === 'object' || !method ) {
method =methods.init;
} else {
$.error( 'Method ' + method + 'does not exist on jQuery.pluginName' );
return this;
}
return method.apply(this, arguments);
};