我正在开发一个WebRTC应用程序,它使用Node.js在两个客户端之间建立连接,使用RTCMulticonnection。它是单向视频,双向音频连接。接收视频流的客户端具有存储从视频流创建的剪辑的功能。目前,我有一些代码,可以以HTML blob的形式创建剪辑。需要捕获存储在blob中的信息并将其存储在Node.js服务器本地的文件中。
上传
目前,我正在使用formidable模块使用FormData对象通过jQuery ajax请求将blob上传到服务器。这些文件存储为没有文件扩展名的二进制文件,而不是MP4或其他类似的视频格式。我需要的是一种方法,将FormData blob转换为视频文件格式并将其存储在本地(HTML页面上的blob视频是'video / webm'格式)或利用此二进制文件进行下载的方式,所以它可以稍后在客户端显示为视频。
客户端
connection.streams[recStreamId].stopRecording(function (blob) {
var form = document.createElement('form');
var mediaElement = document.createElement('video');
mediaElement.autoplay = false;
mediaElement.controls = true;
mediaElement.src = URL.createObjectURL(blob.video);
mediaElement.style.width= '100%';
form.appendChild(mediaElement);
document.getElementById("saved-videos").appendChild(form);
var filename = Date.now();
uploadToServer({cid: cid, vidpath: filename, fname: "video", blob: blob.video});
uploadToServer({cid: cid, vidpath: filename, fname: "audio", blob: blob.audio});
return true;
}, {audio: true, video: true});
服务器侧
var mkdirp = require('mkdirp');
var formidable = require('formidable');
var app = protocol.createServer(options, function (req, res) {
var router = {
post: {},
get: {}
};
router.post['/upload_video'] = function(req, res){
console.log("Uploading");
var form = new formidable.IncomingForm();
var path;
var fname;
var vid;
var vidpath;
form.parse(req, function(err, fields, files){
if (err)
res.writeHead(err.status, err.headers);
res.end();
cid = fields.cid;
vidpath = fields.vidpath;
fname = fields.fname;
vid = files.data;
console.log(fields);
});
form.on('end', function(){
//Directory specific to the user with ID=cid
path = videoPath+cid+"/";
//If the directory does not already exist, create it
mkdirp(path, function(err) {
if (err){
res.writeHead(err.status, err.headers);
res.end();
}
path = path + vidpath + "/";
mkdirp(path, function(err){
if (err){
res.writeHead(err.status, err.headers);
res.end();
}
console.log(vid);
fs.copy(vid.path, path + fname, function(err) {
if (err){
res.writeHead(err.status, err.headers);
res.end();
}
});
});
});
});
}
}
文件已成功存储在服务器端。如果我在浏览器中打开其中一个视频文件,则视频会成功播放。这不是强制性功能,因为它们永远不会从服务器端打开,但是它们需要在客户端可检索和显示。
下载
我目前正在使用fs.readfile下载这些文件。由于此blob同时具有视频和音频组件,因此以下列格式将一个blob存储到服务器:
__dirname + userid + "/" + videoid + "/video" // video component
__dirname + userid + "/" + videoid + "/audio" // audio component
//Example - C:/project/videos/user4/video2/video
//Example - C:/project/videos/user4/video2/audio
服务器侧
使用fs.readFile下载这些文件,并通过HTTP响应将返回的缓冲区发送到客户端。
router.get['/downloadVideo'] = function(req, res){
var query = url.parse(req.url, true).query;
var response = {query: query};
if (query.video == "true") query.video = true;
if (query.video == "false") query.video = false;
if (query.audio == "true") query.audio = true;
if (query.audio == "false") query.audio = false;
var num_remaining = 0;
if (query.audio) num_remaining++;
if (query.video) num_remaining++;
if (query.video){
fs.readFile(videoPath + query.cid + "/" + query.dir + "/video", function(err, buf){
console.log("Downloading " + query.dir + "/video");
num_remaining--;
response.videobuf = buf;
if (num_remaining == 0)
res.end(JSON.stringify(response));
});
}
if (query.audio){
fs.readFile(videoPath + query.cid + "/" + query.dir + "/audio", function(err, buf){
console.log("Downloading " + query.dir + "/audio");
num_remaining--;
response.audiobuf = buf;
if (num_remaining == 0)
res.end(JSON.stringify(response));
});
}
}
客户端
使用jQuery和ajax下载视频。 displayVideo()中的数据对象包含两个缓冲区 - videobuf和audiobuf--它们是通过fs.readFile()下载的文件中的缓冲区。这就是问题所在。正在创建的blob已成功创建,但数据在显示视频的范围内不正确。视频元素已创建,但视频格式不正确。
function downloadVideos(data){
var paths = JSON.parse(data).data;
console.log(paths);
for (var p in paths){
var path = paths[p];
var query = "";
query += "?dir="+path.dir;
query += "&video="+path.video;
query += "&audio="+path.audio;
query += "&cid="+cid;
$.ajax({
type: "GET",
url: url + "/downloadVideo"+query,
data: {}
}).done(displayVideo);
}
}
function displayVideo(data, textStatus, response){
var result = JSON.parse(data);
console.log(result);
var blob = new Blob(result.videobuf.data, {type: "video/webm"});
console.log(blob);
var mediaElement = document.createElement('video');
mediaElement.id = result.query.dir;
mediaElement.autoplay = false;
mediaElement.controls = true;
mediaElement.src = URL.createObjectURL(blob);
mediaElement.style.width= '100%';
document.getElementById("saved-videos").appendChild(mediaElement);
}
我知道这是很多信息,我希望尽可能多地包含详细信息,以便明确我的所有功能所在以及我如何完成所有工作。如果需要其他任何东西请告诉我,但我认为这应该涵盖所有内容。