使用 qt 显示带有 alpha 通道的视频
Displaying a video with an alpha channel using qt
我需要用qt显示RGBA编码的视频(即背景透明的视频)。这个想法是实时合并视频。我通常使用 libmpv 但它似乎不允许渲染透明背景视频。
我正在尝试使用带有以下代码的 QMediaPlayer:
QMainWindow w;
w.resize(1920,1080);
QVideoWidget videoWidget(&w);
videoWidget.move(0,100);
videoWidget.resize(1920,1080);
QMediaPlayer *player = new QMediaPlayer(&w);
w.resize(w.size());
player->setMedia( QUrl::fromLocalFile(PATH+"video2.mov") );
player->setVideoOutput(&videoWidget);
w.show();
player->play();
这成功加载了视频(这是一个 RGBA mov 视频),但是用黑色背景填充了视频小部件,它应该是透明的,从而覆盖了视频播放器后面的任何项目。
有什么方法可以使用 QVideoPlayer/QVideoWidget 实际加载透明视频吗?如果没有,是否有有效的替代方案(我宁愿不使用较低级别的解决方案,如 opencv)。
非常感谢,
弗雷德
这是我最终找到的解决方案:
QAbstractVideoSurface 的子类:
class alphaVideoDrawer : public QAbstractVideoSurface
{
Q_OBJECT
public:
alphaVideoDrawer(QLabel *displayLbl);
private:
QLabel *displayLbl;
protected:
bool present(const QVideoFrame &frame);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_ARGB32;
}
};
Surface 将接收帧转换并转发给显示视频的 qlabel。
alphaVideoDrawer::alphaVideoDrawer(QLabel *displayLbl):displayLbl(displayLbl)
{
}
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
bool alphaVideoDrawer::present(const QVideoFrame &frame)
{
QImage image = qt_imageFromVideoFrame(frame);
displayLbl->setPixmap(QPixmap::fromImage(image));
return true;
}
然后我们将 QLabel 子类化,这将是我们的视频输出:
class alphaVideo : public QLabel
{
Q_OBJECT
public:
alphaVideo(QLabel *parent = nullptr);
private:
alphaVideoDrawer *videoDrawer;
QMediaPlayer *videoPlayer;
QMediaPlaylist *playlist;
};
加载抽屉和播放器并启动 playing/rendering 视频:
alphaVideo::alphaVideo(QLabel *parent): QLabel(parent)
{
setStyleSheet("QLabel { background-color : transparent; }");
videoDrawer = new alphaVideoDrawer(this);
videoPlayer = new QMediaPlayer(this);
playlist = new QmediaPlaylist();
videoPlayer->setPlaylist(playlist);
videoPlayer->setVideoOutput(videoDrawer);
playlist->addMedia( Qurl::fromLocalFile(“your RGBA video file.mp4”) );
videoPlayer->play();
}
我需要用qt显示RGBA编码的视频(即背景透明的视频)。这个想法是实时合并视频。我通常使用 libmpv 但它似乎不允许渲染透明背景视频。 我正在尝试使用带有以下代码的 QMediaPlayer:
QMainWindow w;
w.resize(1920,1080);
QVideoWidget videoWidget(&w);
videoWidget.move(0,100);
videoWidget.resize(1920,1080);
QMediaPlayer *player = new QMediaPlayer(&w);
w.resize(w.size());
player->setMedia( QUrl::fromLocalFile(PATH+"video2.mov") );
player->setVideoOutput(&videoWidget);
w.show();
player->play();
这成功加载了视频(这是一个 RGBA mov 视频),但是用黑色背景填充了视频小部件,它应该是透明的,从而覆盖了视频播放器后面的任何项目。
有什么方法可以使用 QVideoPlayer/QVideoWidget 实际加载透明视频吗?如果没有,是否有有效的替代方案(我宁愿不使用较低级别的解决方案,如 opencv)。
非常感谢,
弗雷德
这是我最终找到的解决方案:
QAbstractVideoSurface 的子类:
class alphaVideoDrawer : public QAbstractVideoSurface
{
Q_OBJECT
public:
alphaVideoDrawer(QLabel *displayLbl);
private:
QLabel *displayLbl;
protected:
bool present(const QVideoFrame &frame);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_ARGB32;
}
};
Surface 将接收帧转换并转发给显示视频的 qlabel。
alphaVideoDrawer::alphaVideoDrawer(QLabel *displayLbl):displayLbl(displayLbl)
{
}
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
bool alphaVideoDrawer::present(const QVideoFrame &frame)
{
QImage image = qt_imageFromVideoFrame(frame);
displayLbl->setPixmap(QPixmap::fromImage(image));
return true;
}
然后我们将 QLabel 子类化,这将是我们的视频输出:
class alphaVideo : public QLabel
{
Q_OBJECT
public:
alphaVideo(QLabel *parent = nullptr);
private:
alphaVideoDrawer *videoDrawer;
QMediaPlayer *videoPlayer;
QMediaPlaylist *playlist;
};
加载抽屉和播放器并启动 playing/rendering 视频:
alphaVideo::alphaVideo(QLabel *parent): QLabel(parent)
{
setStyleSheet("QLabel { background-color : transparent; }");
videoDrawer = new alphaVideoDrawer(this);
videoPlayer = new QMediaPlayer(this);
playlist = new QmediaPlaylist();
videoPlayer->setPlaylist(playlist);
videoPlayer->setVideoOutput(videoDrawer);
playlist->addMedia( Qurl::fromLocalFile(“your RGBA video file.mp4”) );
videoPlayer->play();
}