我如何使用 QMediaPlayer 播放流
How do i play a stream with QMediaPlayer
我已经设置了服务器和视频流,以便我可以使用以下命令行通过 ffplay 连接到流:
ffplay rtmp://<IP>/path
是否可以使用 QMediaPlayer QMediaContent 或其他东西连接到此流?
或者我可以使用 ffserver 创建的任何其他类型的流。
使用与 ffplay 相同的路径导致 "Unsupported url scheme!"
通过进一步的实验,我尝试了 ffserver http 服务器流式传输,但最终以 Qt 在 MFStreamer::doRead()
中崩溃而告终
显然它应该为 MFStreamer 调用 BeginRead 但它没有。
如何使用 QMediaPlayer 播放视频流?
编辑:这是我的代码
videotest.cpp
#include "videotest.h"
#include <QVBoxLayout>
#include <QVideoWidget>
#include <qmediaplayer.h>
#include <QMediaContent>
#include <QNetworkAccessManager>
#include <QNetworkReply>
struct VideoTest::Private
{
QMediaPlayer * mediaPlayer;
QNetworkAccessManager * networkAccessManager;
QNetworkReply * reply;
};
VideoTest::VideoTest(QWidget *parent)
: QMainWindow(parent)
{
d = new Private;
d->mediaPlayer = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
d->networkAccessManager = new QNetworkAccessManager(this);
ui.setupUi(this);
QVideoWidget * videoWidget = new QVideoWidget(ui.centralWidget);
videoWidget->show();
QPalette palette = videoWidget->palette();
palette.setColor(QPalette::Background, QColor(0, 0, 0));
videoWidget->setPalette(palette);
ui.videoLayout->addWidget(videoWidget);
d->mediaPlayer->setVideoOutput(videoWidget);
connect(ui.playButton, SIGNAL(clicked()), d->mediaPlayer, SLOT(play()));
connect(ui.pauseButton, SIGNAL(clicked()), d->mediaPlayer, SLOT(pause()));
connect(ui.videoUrlEdit, SIGNAL(editingFinished()), this, SLOT(sourceChanged()));
connect(d->mediaPlayer, SIGNAL(error()), this, SLOT(stateChanged()));
connect(d->mediaPlayer, SIGNAL(stateChanged), this, SLOT(stateChanged()));
}
VideoTest::~VideoTest()
{
delete d;
}
void VideoTest::sourceChanged()
{
d->reply = d->networkAccessManager->get(QNetworkRequest(ui.videoUrlEdit->text()));
if(d->reply)
{
connect(d->reply, SIGNAL(readyRead()), this, SLOT(networkRequestReady()));
}
}
void VideoTest::stateChanged()
{
QString text = ui.textEdit->toPlainText();
text.append("\n").append(d->mediaPlayer->errorString()).append(" : ").append(d->mediaPlayer->mediaStatus());
ui.textEdit->setText(text);
}
void VideoTest::networkRequestReady()
{
d->mediaPlayer->setMedia(QMediaContent(), d->reply);
}
videotest.h
#ifndef VIDEOTEST_H
#define VIDEOTEST_H
#include <QtWidgets/QMainWindow>
#include "ui_videotest.h"
class VideoTest : public QMainWindow
{
Q_OBJECT
public:
VideoTest(QWidget *parent = 0);
~VideoTest();
public slots:
void sourceChanged();
void stateChanged();
void networkRequestReady();
private:
Ui::VideoTestClass ui;
struct Private;
Private * d;
};
#endif // VIDEOTEST_H
我找到了让它工作的方法。
我放弃了 Qt。 Qt 的人坚持认为它应该工作,但无法生成任何工作的配置。他们说如果你从 VLC 流式传输它应该可以工作,但我没有让它工作。我还尝试了 ffmpeg、ffserver 和 nginx rtmp 流媒体。我让这些东西与 mplayer、ffplay、VLC 一起工作,有些甚至与 Windows Media Player 一起工作,但从来没有与 QMediaPlayer 一起工作。
我试着把 URL 给 setMedia。
我尝试制作一个自定义 QIODevice 来读取流数据并将该数据提供给使用 StreamPlayback 初始化的 QMediaPlayer,但它无法成功读取数据。
最后,我所需要的只是播放流的东西,一个 QWidget 并且没有 GPL 许可。
跟随 these instructions 很容易,但您需要记住将头文件从 vlc-qt/windows/vlc_headers/2.2/ 复制到 vlc/sdk/include/vlc/plugins(原文如此)。这很重要,如果你不这样做,你可能会在编译过程中出错。请注意,如果您的平台版本与我的不匹配,这些路径可能会有所不同。另外,您阅读本文时可能没有必要。
VideoTest.h
#ifndef VIDEOTEST_H_
#define VIDEOTEST_H_
#include <QtWidgets/QMainWindow>
#include "ui_videotest.h"
class VideoTest: public QMainWindow
{
Q_OBJECT
public:
VideoTest(QWidget * p_parent = 0);
~VideoTest();
public slots:
void sourceChanged();
private:
struct Private;
Private * d;
Ui::VideoTestClass ui;
};
#endif
videotest.cpp
#include "videotest.h"
#include <vlc-qt/Common.h>
#include <vlc-qt/Instance.h>
#include <vlc-qt/Media.h>
#include <vlc-qt/MediaPlayer.h>
#include <vlc-qt/WidgetVideo.h>
struct VideoTest::Private
{
VlcInstance * vlcInstance;
VlcMediaPlayer * vlcMediaPlayer;
VlcMedia * vlcMedia;
VlcWidgetVideo * vlcVideoWidget;
};
VideoTest::VideoTest(QWidget * p_parent)
{
d = new Private();
ui.setupUi(this);
d->vlcMedia = 0;
d->vlcInstance = new VlcInstance(VlcCommon::args(), this);
d->vlcMediaPlayer = new VlcMediaPlayer(d->vlcInstance);
d->vlcVideoWidget = new VlcWidgetVideo(this);
d->vlcMediaPlayer->setVideoWidget(d->vlcVideoWidget);
d->vlcVideoWidget->setMediaPlayer(d->vlcMediaPlayer);
ui.videoLayout->addWidget(d->vlcVideoWidget);
connect(ui.playButton, SIGNAL(clicked()), d->vlcMediaPlayer, SLOT(play()));
connect(ui.pauseButton, SIGNAL(clicked()), d->vlcMediaPlayer, SLOT(pause()));
connect(ui.videoUrlEdit, SIGNAL(editingFinished()), this, SLOT(sourceChanged()));
}
VideoTest::~VideoTest()
{
delete d->vlcInstance;
delete d->vlcMediaPlayer;
delete d->vlcMedia;
delete d;
}
VideoTest::sourceChanged()
{
QUrl url(ui.videoUrlEdit->test());
if(url.isValid() == false)
{
return;
}
d->vlcMediaPlayer->stop();
delete d->vlcMedia;
d->vlcMedia = new VlcMedia(url.toString(), d->vlcInstance);
d->vlcMediaPlayer->open(d->vlcMedia);
}
VideoTest.ui
自己做,我不为你工作:D
只要确保它有 pauseButton、playButton、videoUrlEdit(QLineEdit) 和 videoLayout 将插入视频小部件。
我刚刚使用 setMedia(QUrl("http://127.0.0.1:8080"));
成功地通过 C++ QMediaPlayer 在 QML VideoOutput 中播放流
流是由 VLC 媒体播放器使用 8080 端口的 HTTP 创建的。通过 setMedia(QMediaContent(), &localFile);
.
将 VLC 媒体播放器创建的流传递给 QMediaPlayer,我也成功地将其播放到本地文件
我已经设置了服务器和视频流,以便我可以使用以下命令行通过 ffplay 连接到流:
ffplay rtmp://<IP>/path
是否可以使用 QMediaPlayer QMediaContent 或其他东西连接到此流?
或者我可以使用 ffserver 创建的任何其他类型的流。
使用与 ffplay 相同的路径导致 "Unsupported url scheme!"
通过进一步的实验,我尝试了 ffserver http 服务器流式传输,但最终以 Qt 在 MFStreamer::doRead()
中崩溃而告终显然它应该为 MFStreamer 调用 BeginRead 但它没有。
如何使用 QMediaPlayer 播放视频流?
编辑:这是我的代码
videotest.cpp
#include "videotest.h"
#include <QVBoxLayout>
#include <QVideoWidget>
#include <qmediaplayer.h>
#include <QMediaContent>
#include <QNetworkAccessManager>
#include <QNetworkReply>
struct VideoTest::Private
{
QMediaPlayer * mediaPlayer;
QNetworkAccessManager * networkAccessManager;
QNetworkReply * reply;
};
VideoTest::VideoTest(QWidget *parent)
: QMainWindow(parent)
{
d = new Private;
d->mediaPlayer = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
d->networkAccessManager = new QNetworkAccessManager(this);
ui.setupUi(this);
QVideoWidget * videoWidget = new QVideoWidget(ui.centralWidget);
videoWidget->show();
QPalette palette = videoWidget->palette();
palette.setColor(QPalette::Background, QColor(0, 0, 0));
videoWidget->setPalette(palette);
ui.videoLayout->addWidget(videoWidget);
d->mediaPlayer->setVideoOutput(videoWidget);
connect(ui.playButton, SIGNAL(clicked()), d->mediaPlayer, SLOT(play()));
connect(ui.pauseButton, SIGNAL(clicked()), d->mediaPlayer, SLOT(pause()));
connect(ui.videoUrlEdit, SIGNAL(editingFinished()), this, SLOT(sourceChanged()));
connect(d->mediaPlayer, SIGNAL(error()), this, SLOT(stateChanged()));
connect(d->mediaPlayer, SIGNAL(stateChanged), this, SLOT(stateChanged()));
}
VideoTest::~VideoTest()
{
delete d;
}
void VideoTest::sourceChanged()
{
d->reply = d->networkAccessManager->get(QNetworkRequest(ui.videoUrlEdit->text()));
if(d->reply)
{
connect(d->reply, SIGNAL(readyRead()), this, SLOT(networkRequestReady()));
}
}
void VideoTest::stateChanged()
{
QString text = ui.textEdit->toPlainText();
text.append("\n").append(d->mediaPlayer->errorString()).append(" : ").append(d->mediaPlayer->mediaStatus());
ui.textEdit->setText(text);
}
void VideoTest::networkRequestReady()
{
d->mediaPlayer->setMedia(QMediaContent(), d->reply);
}
videotest.h
#ifndef VIDEOTEST_H
#define VIDEOTEST_H
#include <QtWidgets/QMainWindow>
#include "ui_videotest.h"
class VideoTest : public QMainWindow
{
Q_OBJECT
public:
VideoTest(QWidget *parent = 0);
~VideoTest();
public slots:
void sourceChanged();
void stateChanged();
void networkRequestReady();
private:
Ui::VideoTestClass ui;
struct Private;
Private * d;
};
#endif // VIDEOTEST_H
我找到了让它工作的方法。
我放弃了 Qt。 Qt 的人坚持认为它应该工作,但无法生成任何工作的配置。他们说如果你从 VLC 流式传输它应该可以工作,但我没有让它工作。我还尝试了 ffmpeg、ffserver 和 nginx rtmp 流媒体。我让这些东西与 mplayer、ffplay、VLC 一起工作,有些甚至与 Windows Media Player 一起工作,但从来没有与 QMediaPlayer 一起工作。
我试着把 URL 给 setMedia。 我尝试制作一个自定义 QIODevice 来读取流数据并将该数据提供给使用 StreamPlayback 初始化的 QMediaPlayer,但它无法成功读取数据。
最后,我所需要的只是播放流的东西,一个 QWidget 并且没有 GPL 许可。
跟随 these instructions 很容易,但您需要记住将头文件从 vlc-qt/windows/vlc_headers/2.2/ 复制到 vlc/sdk/include/vlc/plugins(原文如此)。这很重要,如果你不这样做,你可能会在编译过程中出错。请注意,如果您的平台版本与我的不匹配,这些路径可能会有所不同。另外,您阅读本文时可能没有必要。
VideoTest.h
#ifndef VIDEOTEST_H_
#define VIDEOTEST_H_
#include <QtWidgets/QMainWindow>
#include "ui_videotest.h"
class VideoTest: public QMainWindow
{
Q_OBJECT
public:
VideoTest(QWidget * p_parent = 0);
~VideoTest();
public slots:
void sourceChanged();
private:
struct Private;
Private * d;
Ui::VideoTestClass ui;
};
#endif
videotest.cpp
#include "videotest.h"
#include <vlc-qt/Common.h>
#include <vlc-qt/Instance.h>
#include <vlc-qt/Media.h>
#include <vlc-qt/MediaPlayer.h>
#include <vlc-qt/WidgetVideo.h>
struct VideoTest::Private
{
VlcInstance * vlcInstance;
VlcMediaPlayer * vlcMediaPlayer;
VlcMedia * vlcMedia;
VlcWidgetVideo * vlcVideoWidget;
};
VideoTest::VideoTest(QWidget * p_parent)
{
d = new Private();
ui.setupUi(this);
d->vlcMedia = 0;
d->vlcInstance = new VlcInstance(VlcCommon::args(), this);
d->vlcMediaPlayer = new VlcMediaPlayer(d->vlcInstance);
d->vlcVideoWidget = new VlcWidgetVideo(this);
d->vlcMediaPlayer->setVideoWidget(d->vlcVideoWidget);
d->vlcVideoWidget->setMediaPlayer(d->vlcMediaPlayer);
ui.videoLayout->addWidget(d->vlcVideoWidget);
connect(ui.playButton, SIGNAL(clicked()), d->vlcMediaPlayer, SLOT(play()));
connect(ui.pauseButton, SIGNAL(clicked()), d->vlcMediaPlayer, SLOT(pause()));
connect(ui.videoUrlEdit, SIGNAL(editingFinished()), this, SLOT(sourceChanged()));
}
VideoTest::~VideoTest()
{
delete d->vlcInstance;
delete d->vlcMediaPlayer;
delete d->vlcMedia;
delete d;
}
VideoTest::sourceChanged()
{
QUrl url(ui.videoUrlEdit->test());
if(url.isValid() == false)
{
return;
}
d->vlcMediaPlayer->stop();
delete d->vlcMedia;
d->vlcMedia = new VlcMedia(url.toString(), d->vlcInstance);
d->vlcMediaPlayer->open(d->vlcMedia);
}
VideoTest.ui
自己做,我不为你工作:D
只要确保它有 pauseButton、playButton、videoUrlEdit(QLineEdit) 和 videoLayout 将插入视频小部件。
我刚刚使用 setMedia(QUrl("http://127.0.0.1:8080"));
成功地通过 C++ QMediaPlayer 在 QML VideoOutput 中播放流
流是由 VLC 媒体播放器使用 8080 端口的 HTTP 创建的。通过 setMedia(QMediaContent(), &localFile);
.