我写了一个脚本,基本上可以将歌曲同步到多个客户端。问题是,客户端1总是比客户端2更靠近歌曲。
当客户端1正在播放歌曲,而客户端2按下按钮时,客户端1将当前时间发送到客户端2,以便客户端2可以获取时间并播放mp3。
我试图预加载mp3,以便客户端2不会在歌曲开始时浪费时间加载文件。但是,它仍然晚了+-0.5秒。
//客户
$(document).ready(function() {
var currentId = "";
document.getElementById("audio").load();
$.ajax({
url: '/retrieveId',
type: 'post',
success: function(data) {
currentId = data;
console.log(currentId);
}
});
$('#host').click(function () {
$('#audio')[0].play();
var interval2 = setInterval(function() {
var currTime = document.getElementById('audio').currentTime;
$.ajax({
url: '/startedPlaying',
type: 'post',
data: { time: currTime, minute: '10' },
success: function(data) {
}
});
},10);
});
$('#client').click(function() {
document.getElementById("audio").play();
$.ajax({
url: '/retrieveTime',
type: 'post',
success: function(data) {
document.getElementById("audio").currentTime = data;
}
});
})
});
//服务器
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", function(req, res) {
res.sendFile(path.join(__dirname + "/index.html"));
}).listen(12340);
app.post("/startedPlaying", function(req, res) {
currTime = req.body.time;
res.end();
});
app.post("/retrieveTime", function(req, res) {
res.send(currTime);
res.end();
});
app.post("/retrieveId", function(req, res) {
id++;
res.send(id.toString());
res.end();
});
因此,从根本上讲,我需要有关如何使它们完全同时运行的帮助。
谢谢。
答案 0 :(得分:1)
您需要做的第一件事是在将要同步的两个客户端之间建立通信通道。考虑到您的延迟要求,我猜测这些客户端在物理上彼此接近,并且可能位于同一网络上。在这种情况下,您将受益于创建点对点WebRTC连接以及它们之间的数据通道。通常,客户端可以协商它们共享的网络上的连接,而不必将数据发送到服务器然后再发送回去,这减少了该数据通道的延迟。
接下来,像往常一样缓冲媒体。您可以使用.buffered
来确定要缓冲的时间范围。通常,您可以依靠canplaythrough
event来确定播放器何时有足够的缓冲空间来播放,而不必再次重新缓冲。
然后,确定哪个端将是“主”端,所有同步数据都将来自此端。开始双方播放。
通常,随着播放的进行,主机应将其currentTime
发送给其他客户端。这些客户收到邮件后,应检查自己的currentTime
,以了解他们有多远。从那里,他们应该对如何赶超进行计算。例如,如果主服务器位于100.100
,而从客户机位于100.000
,则它需要占用100毫秒。如果将playbackRate
设置为1.01
,则将花费10秒以上的时间。或者,1.02
,您将在5秒钟内完成化妆。
您将想出一些公式来确定不同步的严重程度并易于解决。您还将希望对播放速度有一些合理的限制。 (例如,您可能不希望快/慢超过10%来进行同步。)此外,如果两者之间的间隔非常差,则可以选择暂停其中一个,将currentTime
设置为其他(通常会导致重新缓冲)并重新开始。
您可以做的改进是还可以确定主/从之间的等待时间。如果主服务器说“现在是12.345s”,并且您在100毫秒后收到该时间戳,则该时间戳实际上是12.445。您可以实施“ ping”操作,以连续测量延迟。更好的是,在每个定时消息上都使用此代码。
这应该使您真正掌握时间,对于大多数用例来说足够。