Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

video缓存,延迟问题 #274

Open
mwb-27 opened this issue Feb 5, 2018 · 27 comments
Open

video缓存,延迟问题 #274

mwb-27 opened this issue Feb 5, 2018 · 27 comments

Comments

@mwb-27
Copy link

mwb-27 commented Feb 5, 2018

video标签本身有缓存机制,我使用mse播放实时流,currentTime永远比buffered.end要慢将近1.5,导致我直播有延迟,请问这个问题该怎么解决。我试过将currentTime设置为buffered.end 的事件,但是会触发waiting事件,表示下一帧不可播放。希望有懂的人给讲解下这里的机制并谈一下可行的解决方案

@xqq
Copy link
Contributor

xqq commented Feb 5, 2018

你减个0.5秒不就完了

@mwb-27
Copy link
Author

mwb-27 commented Feb 5, 2018

@xqq 这个我明白~~那也就是说这个将近1.5s的延迟是没有办法再进一步优化的是吧?我是希望在不卡顿的情况下尽可能的降低延迟

@xqq
Copy link
Contributor

xqq commented Feb 5, 2018

减0.5秒可以优化到0.5秒

@xqq
Copy link
Contributor

xqq commented Feb 5, 2018

另外可以尝试设置enableStashBuffer: false,会降低效率

@mwb-27
Copy link
Author

mwb-27 commented Feb 5, 2018

@xqq 好的,谢谢。我还想请教下我这里碰到的问题,就是这个waiting事件触发的条件,文档上看到是说下一帧不可播放时会触发。但是我看了buffered.end() 的时间明明比currentTime要多1.5秒时间,为什么就触发了waiting事件呢?这里的下一帧指的是I帧还是什么?这个让我很疑惑

@mwb-27
Copy link
Author

mwb-27 commented Feb 5, 2018

@xqq 这个是导致我无法降低延迟的关键,我必须让currentTime慢于buffered.end() 1.5s以上才能确保不触发waiting事件

@xqq
Copy link
Contributor

xqq commented Feb 5, 2018

不是很清楚,waiting事件抛出时视频有卡住么

@mwb-27
Copy link
Author

mwb-27 commented Feb 6, 2018

@xqq 是的,waiting抛出时视频会卡一下,因为触发waiting时currentTime是不会更新的,很快又会触发playing事件,应该是很快下一帧的数据解码完成是可播放的了。目前就是因为这个卡顿现象我没法再进一步优化延迟。

@d02540220
Copy link

@mwb-27 你直播延时大概多少秒?

@winshining
Copy link

winshining commented Mar 24, 2018

@d02540220 flv.js使用http-flv方式播放,1秒不到,我是最近有网友反馈使用flv.js播放我的直播服务器拉流有问题时,我调试时测试的(要开启gop_cache选项),flv.js播放的首屏时间比vlc少得多,flv.js表现非常优秀。

@mwb-27
Copy link
Author

mwb-27 commented Mar 28, 2018

@d02540220 我现在延迟控制在2s以内,大致在1.5s左右

@mwb-27
Copy link
Author

mwb-27 commented Mar 28, 2018

@winshining 我没有用flv.js,我直接调用的MSE的API实现的直播。我后端给的视频流是fmp4的

@notedit
Copy link

notedit commented Apr 7, 2018

@mwb-27 现在确实有这个问题 延迟大概有1.5s ffplay no buffer 模式可以做到0.4s的延迟

@chengsu
Copy link

chengsu commented May 15, 2019

我测试ip摄像头,延迟大约在700ms左右,还有地方可以减少延迟吗?

服务端用node做代理通过websocket推到前端

ffmpeg命令

ffmpeg -rtsp_transport tcp -i rtsp://xxxxxxxx -c copy -f flv http://localhost:3004

前端代码

<script src="//cdn.bootcss.com/flv.js/1.5.0/flv.js"></script>
<video id="videoElement" width="1850"></video>
<script>
    if (flvjs.isSupported()) {
        var video = videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            isLive: true,
            url: 'ws://' + location.search.slice(1),
        }, {
            enableStashBuffer: false
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();


        setTimeout(() => {
            flvPlayer.play();
        }, 2000)

        setInterval(() => {
            if (!video.buffered.length) {
                return;
            }
            let end = video.buffered.end(0);
            let diff = end - video.currentTime;
            if (diff >= 1.5) {
                video.currentTime = end;
            }
        }, 3000);
    }
</script>

对比 jsmpeg 延迟可以做到1s内,应该在300ms左右

@DenySu
Copy link

DenySu commented Jun 16, 2019

我测试ip摄像头,延迟大约在700ms左右,还有地方可以减少延迟吗?

服务端用node做代理通过websocket推到前端

ffmpeg命令

ffmpeg -rtsp_transport tcp -i rtsp://xxxxxxxx -c copy -f flv http://localhost:3004

前端代码

<script src="//cdn.bootcss.com/flv.js/1.5.0/flv.js"></script>
<video id="videoElement" width="1850"></video>
<script>
    if (flvjs.isSupported()) {
        var video = videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            isLive: true,
            url: 'ws://' + location.search.slice(1),
        }, {
            enableStashBuffer: false
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();


        setTimeout(() => {
            flvPlayer.play();
        }, 2000)

        setInterval(() => {
            if (!video.buffered.length) {
                return;
            }
            let end = video.buffered.end(0);
            let diff = end - video.currentTime;
            if (diff >= 1.5) {
                video.currentTime = end;
            }
        }, 3000);
    }
</script>

对比 jsmpeg 延迟可以做到1s内,应该在300ms左右

这样不会出现跳帧的现象么?

@chengsu
Copy link

chengsu commented Jun 17, 2019

@DenySu 有跳帧,但是我的应用场景要求低延迟,可以容忍跳帧。这里也可以改成如果延迟太大,就加快播放速度,延迟降下来后再恢复正常播放速度,但是实测还是会有跳帧。

@evilArsh
Copy link

evilArsh commented Jul 9, 2019

为啥我有1.8秒的延迟啊,我用的node-media-server

@tianwen2976
Copy link

@mwb-27 请问这个currentTime与buffered.end()差1.5s的问题解决了么,我也遇到了。

@chengsu
Copy link

chengsu commented Jul 10, 2020

@evilArsh 1.8s应该是node-media-server内部缓存了关键帧。一般像机编码默认都是2s一个关键帧,如果你在这2s之内点播,node-media-server会直接发前一个关键帧,这个就可能延迟了几百毫秒,而且这个延迟播放时也不会追上来。如果要在浏览器上实现1s内的实时效果,最好还是用webassembly加载解码器直接解码视频,再由canvas画视频,基于video和mse的播放方案很难克服。

@17Sdubin
Copy link

17Sdubin commented Sep 1, 2020

@mwb-27 现在确实有这个问题 延迟大概有1.5s ffplay no buffer 模式可以做到0.4s的延迟

请问1.5s的延迟能再缩短吗?我现在也遇到这个问题

@17Sdubin
Copy link

17Sdubin commented Sep 1, 2020

@d02540220 flv.js使用http-flv方式播放,1秒不到,我是最近有网友反馈使用flv.js播放我的直播服务器拉流有问题时,我调试时测试的(要开启gop_cache选项),flv.js播放的首屏时间比vlc少得多,flv.js表现非常优秀。

请问大神,1s不到,怎么做到的,video自带的缓存,不是缩短到1.5秒就到极限了吗,你用什么办法解决的?

@17Sdubin
Copy link

17Sdubin commented Sep 1, 2020

@xqq 好的,谢谢。我还想请教下我这里碰到的问题,就是这个waiting事件触发的条件,文档上看到是说下一帧不可播放时会触发。但是我看了buffered.end() 的时间明明比currentTime要多1.5秒时间,为什么就触发了waiting事件呢?这里的下一帧指的是I帧还是什么?这个让我很疑惑

请问大神,你这个问题解决了吗?

@ouzhou
Copy link

ouzhou commented Sep 2, 2020

video.currentTime = end;的方案关键是还会导致跳帧, 没有其他办法了吗

@wjy18666
Copy link

我测试ip摄像头,延迟大约在700ms左右,还有地方可以减少延迟吗?

服务端用node做代理通过websocket推到前端

ffmpeg命令

ffmpeg -rtsp_transport tcp -i rtsp://xxxxxxxx -c copy -f flv http://localhost:3004

前端代码

<script src="//cdn.bootcss.com/flv.js/1.5.0/flv.js"></script>
<video id="videoElement" width="1850"></video>
<script>
    if (flvjs.isSupported()) {
        var video = videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            isLive: true,
            url: 'ws://' + location.search.slice(1),
        }, {
            enableStashBuffer: false
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();


        setTimeout(() => {
            flvPlayer.play();
        }, 2000)

        setInterval(() => {
            if (!video.buffered.length) {
                return;
            }
            let end = video.buffered.end(0);
            let diff = end - video.currentTime;
            if (diff >= 1.5) {
                video.currentTime = end;
            }
        }, 3000);
    }
</script>

对比 jsmpeg 延迟可以做到1s内,应该在300ms左右

能提供下你的node.js转码代码吗?我的也是连接网络摄像头,延迟居然10-20s去了,也是用的ffmpeg,代码如下:
var express = require('express')
var expressWebSocket = require('express-ws')
var ffmpeg = require('fluent-ffmpeg')
var WebSocket = require('websocket-stream')
var webSocketStream = require('websocket-stream/stream')

function localServer() {
let app = express();
app.use(express.static(__dirname));
expressWebSocket(app, null, {
perMessageDeflate: true
});
app.ws("/rtsp/:id/", rtspRequestHandle)
app.listen(8888);
console.log("express listened")
}
function rtspRequestHandle(ws, req) {
console.log("rtsp request handle");
const stream = webSocketStream(ws, {
binary: true,
browserBufferTimeout: 1000000
}, {
browserBufferTimeout: 1000000
});
let url = req.query.url;
console.log("rtsp url:", url);
console.log("rtsp params:", req.params);
try {
ffmpeg(url)
.addInputOption("-analyzeduration", "100000", "-max_delay", "1000000")
// .addInputOption("-rtsp_transport", "tcp", "-buffer_size", "102400") // 这里可以添加一些 RTSP 优化的参数
.on("start", function () {
console.log(url, "Stream started.");
})
.on("codecData", function () {
console.log(url, "Stream codecData.")
// 摄像机在线处理
})
.on("error", function (err) {
console.log(url, "An error occured: ", err.message);
})
.on("end", function () {
console.log(url, "Stream end!");
// 摄像机断线的处理
})
.outputFormat("flv").videoCodec("copy").noAudio().pipe(stream);
} catch (error) {
console.log(error);
}
}

localServer()

@wjy18666
Copy link

@xqq 是的,waiting抛出时视频会卡一下,因为触发waiting时currentTime是不会更新的,很快又会触发playing事件,应该是很快下一帧的数据解码完成是可播放的了。目前就是因为这个卡顿现象我没法再进一步优化延迟。

这个你后来解决了吗?我现在也有这样的情况,设置时间过短也会触发waiting事件,感觉要不跳帧,要不卡主,大部分都是waiting的loading卡主

@wjy18666
Copy link

你减个0.5秒不就完了

我的也是按照你的方案来,也会一直触发waiting,最少1.5s,但是业务需求是1s内,不能比rtmp延迟大

@shady-xia
Copy link

shady-xia commented Nov 11, 2021

是会有这样的问题, 建议使用调整播放倍速的方式,比如延迟大于某个值,将video.playbackRate设为1.1,小于即恢复正常,这个是比较好的追帧方案

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests