QML多媒体无法播放用ffmpeg生成的m3u8

QML multimedia cannot play m3u8 that is generated with ffmpeg

提问人:LeXela-ED 提问时间:6/3/2023 最后编辑:נירLeXela-ED 更新时间:6/5/2023 访问量:162

问:

使用以下命令,我尝试通过网络流式传输 IP 摄像机:

ffmpeg -re -i "rtsp://<user>:<password>@<ip>:<port>" -c:v copy -c:a copy -hls_segment_type mpegts -hls_list_size 5 -hls_wrap 5 -hls_time 2 -hls_flags split_by_time -segment_time_delta 1.00 -reset_timestamps 1 -hls_allow_cache 0 -movflags faststart live.m3u8```

此命令生成 live.m3u8 和五个 ts 文件:live0.ts、live1.ts、live2.ts、live3.ts 和 live4转换进行得很顺利。在某个随机点,live.m3u8 的内容如下:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:92
#EXTINF:2.000000,
live2.ts
#EXTINF:2.000000,
live3.ts
#EXTINF:2.035800,
live4.ts
#EXTINF:2.000000,
live0.ts
#EXTINF:1.963278,
live1.ts

但是,当我尝试使用以下QML代码播放live.m3u8时,它只播放了其中的第一段:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtMultimedia 5.15

Window
{
    width: 640
    height: 480
    visible: true

    Item
    {
        anchors.fill: parent

        MediaPlayer
        {
            id: mediaplayer
            source: "path-to-live/live.m3u8"
            videoOutput: videoOutput
        }

        VideoOutput
        {
            id: videoOutput
            anchors.fill: parent
        }

        MouseArea
        {
            anchors.fill: parent
            onPressed: mediaplayer.play();
        }
    }
}

有趣的是:我手动删除了 live.m3u8,显然,ffmpeg 之后又生成了一个!然后我点击了QML程序窗口,令人惊讶的是,它像第一次运行时预期的那样不间断地播放流!

这里有什么问题?我错过了什么?我应该更改 ffmpeg 命令还是对我的 qml 代码做点什么?有任何想法或帮助吗?

先谢谢你。

ffmpeg qml http-live-streaming

评论


答:

0赞 Stephen Quan 6/3/2023 #1

我根本无法开始工作,但是,我怀疑您的问题是在加载时被读取,而不是在按下时被读取。这意味着,如果您在程序运行时重新生成,则其中的信息可能会过时,它不会接受更改。为了获得最新的更改,您应该考虑尽可能晚地分配,例如在点击时。live.m3u8m3u8MouseAream3u8live.m3u8live.m3u8mediaplayer.sourceMouseArea

        MouseArea
        {
            anchors.fill: parent
            onPressed: {
                mediaplayer.source = "";
                mediaplayer.source = "file-url-to-live/live.m3u8";
                mediaplayer.play();
            }
        }

另外,既然你有,你可以转码到任何你想要的东西,那么,你为什么不把它转码到你知道Qt可以播放的单个文件呢?对我来说,以下内容适用于我的 Windows 机器(即我正在强制使用音频编解码器、视频编解码器和文件格式容器)。ffmpegmp3mpeg4avi

ffmpeg -y -i ... -c:v mpeg4 -c:a lipbmp3lame live.avi

另一种选择是使用 mpeg(例如 文件格式容器中以 25 fps 的速度播放的音频)。如果您无法使用,这将是一个更好的选择:mp3mpeg1 videompgavi

ffmpeg -y -i ... -c:v mpeg1video -c:a lipbmp3lame -r 25 live.mpg

即使你有 Qt5.15.x 导入,看起来你使用的是 Qt6 风格的多媒体。

在 Qt5.15.x 中,记录的用法是指 ,而不是相反。UI/UX 位于您可以放置在任何地方并作为顶级组件。将它放在 .事实上,在您的示例中实际上不需要该组件,因此,我对其进行了重构:VideoOutputVideoOutputMediaPlayerVideoOutputMediaPlayerItemItem

// Qt5.15.x version
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtMultimedia 5.15
Window
{
    width: 640
    height: 480
    visible: true
    MediaPlayer
    {
        id: mediaplayer
    }
    VideoOutput
    {
        id: videoOutput
        source: mediaplayer
        anchors.fill: parent
        MouseArea {
            anchors.fill: parent
            onPressed: {
                mediaplayer.source = "";
                mediaplayer.source = "file:///C:/Temp/Vid/live.avi";
                mediaplayer.play();
            }
        }
    }
}

在Qt6中,不需要为导入提供版本号,因此原始代码仍然存在。但是,我关于没有必要的评论也成立:Item

// Qt6 version
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import QtMultimedia
Window {
    MediaPlayer {
        id: mediaPlayer
        videoOutput: videoOutput
    }
    VideoOutput {
        id: videoOutput
        anchors.fill: parent
        MouseArea {
            anchors.fill: parent
            onPressed: {
                mediaplayer.source = "";
                mediaplayer.source = "file:///C:/Temp/Vid/live.avi";
                mediaplayer.play();
            }
        }
    }
}

引用:

评论

0赞 LeXela-ED 6/5/2023
首先,我感谢您的回答。事实上,它需要相机长时间开启和工作,以及在线流媒体。一种可能的选择是使用 HLS 仅记录和保留最近的片段。所以,我不能使用其他多路复用器,比如你指出的那个。对于QML方面,是的,你是对的。我将样式更改为Qt Qt5.15.x。但是,它没有帮助。甚至我尝试使用Qt6。它也无济于事!:(甚至我试过看看QML方面是否有问题。他们也只玩了第一部分。ffplayVLC