licode
来源:互联网 发布:驾校抢约车软件 编辑:程序博客网 时间:2024/05/20 04:27
mongodb
基于分布式文件存储,非关系数据库,类似json的bson格式http://www.mongodb.org/downloadsmongo 10.50.141.25/nuvedb // 用IP连接某个数据库 mongo --port 27017show 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 // 启动从服务器,带logmongodump -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
<pre class="html" name="code">基于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
工具
<p><span style="font-family: Arial, Helvetica, sans-serif;">js打包工具compiler.jar // </span><span style="font-family: Arial, Helvetica, sans-serif;">java -jar compiler.jar --js xxx.js</span></p>node-GYP 项目构建工具 node_addon node调用Linux下的动态库,库由c++实现。<span style="white-space:pre"></span>需要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)创建webAppvar express = require("express");var app = express();// 创建webServervar 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 = "<svg>..." https://code.google.com/p/svg-edit/ 不缓存页面 服务器返回的消息中携带以下值,表示要不要客户端存 客户端:工具中的选项 表示 要不要用显示的内容 // printf("Content-type: text/html\n\n");// window调用iframe:document.getElementById("iframeId").contentWindow.iframeVar = "XXX"; (...contentWindow.iframeFunction(); ...contentWindow.document.getElementById();)// iframe调用window:parent.windowVar = "XXX"; (parent.winFunction();)// window传递数据给不同域的iframewindow: window.parent.iframeId.postMessage(msg, "*");iframe: window.addEventListener("message", msgFunc, false); var msgFunc = function(e) { console.log(e.data);}// 清除所选择的file<input type=file name="fileName"> fileName.outerHTML = fileName.outerHTML; // maybe fileId// 增加divdocument.body.appendChild(div);// 增加livar ul = document.getElementById("ulid");var li = document.createElement("li");li.id = ;...ul.appendChild(li);// 删除某个li if( lis.item(id).id == xxx )var lis = ul.childNodes;ul.removeChild(lis.item(id)); // 删除全部livar total = lis.length;for(var i = 0; i < total; i++) {// 每删除列表中的第一个li, 其他li会重新排列。lis.length, item(0)等都会变化 ul.removeChild(lis.item(0)); }//uuid的生成var uuid = Math.floor(Math.random()*16.0).toString(16);</svg>
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等事件监听
<form method="post" enctype="multipart/form-data" action="/file-upload">
<input type="file" name="thumbnail">
<input type="submit">
</form>
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);
};
- licode
- licode备忘
- licode API (译文)
- ubuntu 编译licode
- Licode Demo搭建
- Ubuntu16.04配置licode
- licode安装使用
- 虚拟机ubuntu 14.04搭建licode
- 虚拟机ubuntu 14.04搭建licode
- Licode(一):入门介绍
- licode的ios最新版本的接入
- Licode(二):Nuve源码分析
- licode 客户端API (译文)【转】
- jsp页面中密码框和文本框长度不一致问题的解决方法
- php mysql事务处理回滚操作
- Ext JS 4倒计时:动态加载和新的类系统
- 人与人之间在八小时之外的差别
- 职业生涯规划的方法
- licode
- java代码检查工具
- java API开发hbase启动错误解决办法
- 2013 年最热门的 20 个 Web 设计趋势
- Redis指令文档
- SQL附加数据库提示 5120错误
- WinCE中的Data/ Prefetch Abort等异常定位(通过map文件)
- qt 透明化方法汇总
- Analog和RF领域经典书籍