首先我先建一个简单的视频流server, 浏览器请求就可以直接播放啦,但是。。。
var http = require('http')
var fs = require('fs')
http.createServer(function(request, response){
var mp4 = 'SX28_hd.mp4';
var stat = fs.statSync(mp4);
response.writeHead(200, {
'Content-Type': 'video/mp4',
'Content-Length': stat.size
})
var readableStream = fs.createReadStream(mp4);
readableStream.pipe(response);
}).listen(3000)
------------------------------我是美丽的分割线-------------------------------------------------------
我再建一个接受视频流的客户端, 代码如下,
var http = require('http')
var fs = require('fs')
var options = {
host:'localhost',
port:'3000',
path:'/',
method:'GET'
}
var writeStream = fs.createWriteStream('file.mp4')
var passedLength = 0;
var lastSize = 0;
var startTime = Date.now();
var totalSize = 0;
var req = http.request(options, function(res){
console.log('STATUS' + res.statusCode)
totalSize = res.headers['content-length'];
console.log(totalSize);
// console.log('HEADERS' + JSON.stringify(res.headers))
// res.setEncoding('utf8')
res.on('data', function(chunk){
// console.log('BODY' + chunk);
passedLength += chunk.length;
writeStream.write(chunk);
})
res.on('end', function(){
writeStream.end();
console.log('xx');
})
})
req.end();
var out = process.stdout;
setTimeout(function show() {
var percent = Math.ceil((passedLength / totalSize) * 100);
var size = Math.ceil(passedLength / 1000000);
var diff = size - lastSize;
lastSize = size;
out.clearLine();
out.cursorTo(0);
out.write('已完成' + size + 'MB, ' + percent + '%, 速度:' + diff * 2 + 'MB/s');
if (passedLength < totalSize) {
setTimeout(show, 50);
} else {
var endTime = Date.now();
console.log();
console.log('共用时:' + (endTime - startTime) / 1000 + '秒。');
}
}, 50);
------------------------------我是美丽的分割线------------------------------------------------------- 但是,如果视频还没有下完, 我就把进程关闭, 发现下载到本地的一部分视频是可以播放的, 我有两个疑问
- 如果时时下载, 客户端(ios 和安卓)一开始下载的那一部分能够播放吗?
- 这样能够支持多客户端播放吗?
------------------------------我是美丽的分割线-------------------------------------------------------
这看起来只是一个静态的文件服务器, 我想要实现一个能够任意跳转点播的视频服务器, 找了很多资料,java在这块很成熟, 有很多开源产品,但nodejs该怎么弄啊? 目前所知的两种协议:rtmp, http live stream, 但这两种协议在nodejs应用呢? 欢迎大家一起讨论啊!!!!
还有一种解决方案, 七牛支持视频切片, 跳转点播,但想自己弄个,而且七牛那api …
mp4格式的视频要边下边播支持拖动,一般要在服务端支持range——拖动选时观看(seek)是基于索引的,mp4的索引在头部,要seek选时观看,播放器会根据索引计算出offset,生成一个带range的http请求去获取数据——这是一般播放器的做法,也有实现的差的没有做这个功能。
rtmp 兼容比较好吧
@TadyCao 感谢你的指导, 已经实现带range的视频,音频播放功能,
把源码放出来,有需要的童鞋也可以参考下
/**
* Created by nodefx on 8/29/14.
*/
var path = require('path');
var fs = require('fs')
var http = require('http')
var url = require('url')
var mime = require('./mime').types
var config = require("./config");
var utils = require("./utils")
var port = 8000;
var server = http.createServer(function(request, response){
var pathname = url.parse(request.url).pathname;
var realpath = path.join("assets", path.normalize(pathname.replace(/\.\./g, "")))
console.log(realpath)
var ext = path.extname(realpath)
ext = ext ? ext.slice(1):"unknown"
var contentType = mime[ext] || "text/plain"
console.log(contentType)
fs.exists(realpath, function(exists) {
if (!exists) {
response.writeHead(404, {
'Content-Type': 'text/plain'
})
response.write("This request URL " + pathname + "was not found on this server");
response.end();
} else {
response.setHeader("Content-Type",contentType);
var stats = fs.statSync(realpath);
if (request.headers["range"]) {
console.log(request.headers["range"])
var range = utils.parseRange(request.headers["range"], stats.size);
console.log(range)
if (range) {
response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + stats.size);
response.setHeader("Content-Length", (range.end - range.start + 1));
var stream = fs.createReadStream(realpath, {
"start": range.start,
"end": range.end
});
response.writeHead('206', "Partial Content");
stream.pipe(response);
} else {
response.removeHeader("Content-Length");
response.writeHead(416, "Request Range Not Satisfiable");
response.end();
}
} else {
var stream = fs.createReadStream(realpath);
response.writeHead('200', "Partial Content");
stream.pipe(response);
}
}
})
})
server.listen(port)
刚刚和ios和安卓客户端 测试下了,客户端可以直接调用本地播放器播放,意味着可以做个类似blibli的视频播放的app啦, 完整代码在 https://github.com/node-node/vedio_stream
@node-node 帮忙看看我这个问题:http://cnodejs.org/topic/5400406dcd66f2eb3705de38#54007d8dcd66f2eb37123c25 其实跟你的程序查不多,"stream.pipe(response);"超过14分钟左右会收到response.event.close,目前无解。不知道你的程序有没有遇到相同现象。