gpt4 book ai didi

javascript - 当 playlist.m3u8 文件不断更新时,如何播放 HLS 流?

转载 作者:行者123 更新时间:2023-12-04 22:50:06 25 4
gpt4 key购买 nike

我正在使用 MediaRecorder 从 MediaStream 以 webm 格式记录我的实时视频 block ,并使用 ffmpeg 将这些 block 转换为服务器上的 .ts 文件,然后使用以下代码更新我的 playlist.m3u8 文件:

function generateM3u8Playlist(fileDataArr, playlistFp, isLive, cb) {
var durations = fileDataArr.map(function(fd) {
return fd.duration;
});
var maxT = maxOfArr(durations);

var meta = [
'#EXTM3U',
'#EXT-X-VERSION:3',
'#EXT-X-MEDIA-SEQUENCE:0',
'#EXT-X-ALLOW-CACHE:YES',
'#EXT-X-TARGETDURATION:' + Math.ceil(maxT),
];

fileDataArr.forEach(function(fd) {
meta.push('#EXTINF:' + fd.duration.toFixed(2) + ',');
meta.push(fd.fileName2);
});

if (!isLive) {
meta.push('#EXT-X-ENDLIST');
}

meta.push('');
meta = meta.join('\n');

fs.writeFile(playlistFp, meta, cb);
}
这里 fileDataArr保存已创建的所有 block 的信息。
之后,我使用此代码创建一个 hls 服务器:
var runStreamServer = (function(streamFolder) {
var executed = false;
return function(streamFolder) {
if (!executed) {
executed = true;
var HLSServer = require('hls-server')
var http = require('http')

var server = http.createServer()
var hls = new HLSServer(server, {
path: '/stream', // Base URI to output HLS streams
dir: 'C:\\Users\\Work\\Desktop\\live-stream\\webcam2hls\\videos\\' + streamFolder // Directory that input files are stored
})
console.log("We are going to stream from folder:" + streamFolder);
server.listen(8000);
console.log('Server Listening on Port 8000');
}
};
})();
问题是,如果我停止创建新 block 然后使用 hls 服务器链接: http://localhost:8000/stream/playlist.m3u8然后视频在 VLC 中播放,但如果我在录制过程中尝试播放,它会继续加载文件但不播放。我希望它在创建新 block 和更新 playlist.m3u8 时播放。 generateM3u8Playlist 中的怪癖功能是它添加了 '#EXT-X-ENDLIST'停止录制后到播放列表文件。
该软件仍在生产中,因此代码有点困惑。谢谢你的任何答案。
生成 blob 的客户端如下:
var mediaConstraints = {
video: true,
audio:true
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
console.log('will start capturing and sending ' + (DT / 1000) + 's videos when you press start');
var mediaRecorder = new MediaStreamRecorder(stream);

mediaRecorder.mimeType = 'video/webm';

mediaRecorder.ondataavailable = function(blob) {
var count2 = zeroPad(count, 5);
// here count2 just creates a blob number
console.log('sending chunk ' + name + ' #' + count2 + '...');
send('/chunk/' + name + '/' + count2 + (stopped ? '/finish' : ''), blob);
++count;
};
}
// Here we have the send function which sends our blob to server:
function send(url, blob) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);

xhr.responseType = 'text/plain';
xhr.setRequestHeader('Content-Type', 'video/webm');
//xhr.setRequestHeader("Content-Length", blob.length);

xhr.onload = function(e) {
if (this.status === 200) {
console.log(this.response);
}
};
xhr.send(blob);
}
接收XHR请求的代码如下:
var parts = u.split('/');
var prefix = parts[2];
var num = parts[3];
var isFirst = false;
var isLast = !!parts[4];

if ((/^0+$/).test(num)) {
var path = require('path');
shell.mkdir(path.join(__dirname, 'videos', prefix));
isFirst = true;
}

var fp = 'videos/' + prefix + '/' + num + '.webm';
var msg = 'got ' + fp;
console.log(msg);
console.log('isFirst:%s, isLast:%s', isFirst, isLast);

var stream = fs.createWriteStream(fp, { encoding: 'binary' });
/*stream.on('end', function() {
respond(res, ['text/plain', msg]);
});*/

//req.setEncoding('binary');

req.pipe(stream);
req.on('end', function() {
respond(res, ['text/plain', msg]);

if (!LIVE) { return; }

var duration = 20;
var fd = {
fileName: num + '.webm',
filePath: fp,
duration: duration
};
var fileDataArr;
if (isFirst) {
fileDataArr = [];
fileDataArrs[prefix] = fileDataArr;
} else {
var fileDataArr = fileDataArrs[prefix];
}
try {
fileDataArr.push(fd);
} catch (err) {
fileDataArr = [];
console.log(err.message);
}
videoUtils.computeStartTimes(fileDataArr);

videoUtils.webm2Mpegts(fd, function(err, mpegtsFp) {
if (err) { return console.error(err); }
console.log('created %s', mpegtsFp);

var playlistFp = 'videos/' + prefix + '/playlist.m3u8';

var fileDataArr2 = (isLast ? fileDataArr : lastN(fileDataArr, PREV_ITEMS_IN_LIVE));

var action = (isFirst ? 'created' : (isLast ? 'finished' : 'updated'));

videoUtils.generateM3u8Playlist(fileDataArr2, playlistFp, !isLast, function(err) {
console.log('playlist %s %s', playlistFp, (err ? err.toString() : action));
});
});


runStreamServer(prefix);
}

最佳答案

您没有向我们展示您如何使用 MediaRecorder生成您的数据“ block ”。你用吗its ondataavailable event以此目的?
如果是这样,请记住这一点:您必须连接 ondataavailable 交给您的所有 block 。获取有效的 .webm(或 .matroska)数据流。
您不能只在媒体文件中存储任意数据 block 并期望它播放。甚至 ffmpeg 也需要将所有 block 流式传输到它以生成有效的输出。这是因为前几个 block 包含 mandatory .webm initialization segment ,而其他 block 没有。

关于javascript - 当 playlist.m3u8 文件不断更新时,如何播放 HLS 流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65381353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com