如何在PyQt5的QVideoWidget中实现手机拍摄视频的旋转播放
解决方案
你遇到的竖拍视频横放问题是因为手机拍摄的视频会将旋转参数写入文件元数据,QVideoWidget默认不会读取该参数自动调整播放朝向。我们可以通过QGraphicsVideoItem替代QVideoWidget实现播放时动态旋转,无需修改原视频文件。
实现逻辑
- 用
QGraphicsView+QGraphicsVideoItem组合替换原生QVideoWidget,该组件支持自由旋转视频画面 - 读取视频元数据中的旋转角度参数,自动调整画面朝向
- 旋转后自动适配显示窗口尺寸,避免画面偏移或超出显示区域
- 若元数据无旋转参数,可通过判断视频原生宽高比兜底调整
完整修改代码
主程序代码
from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia from PyQt5.QtMultimediaWidgets import QGraphicsVideoItem from GUI import Ui_MainWindow class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, **kwargs): QtWidgets.QMainWindow.__init__(self, *args, **kwargs) self.setupUi(self) # 隐藏原有QVideoWidget,替换为支持旋转的GraphicsView方案 self.widget.hide() self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget) self.graphicsView.setGeometry(self.widget.geometry()) self.scene = QtWidgets.QGraphicsScene(self) self.graphicsView.setScene(self.scene) self.videoItem = QGraphicsVideoItem() self.scene.addItem(self.videoItem) # 配置显示效果,隐藏滚动条、开启平滑缩放 self.graphicsView.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform) self.graphicsView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.graphicsView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) # 初始化播放器 self.mediaPlayer = QtMultimedia.QMediaPlayer(self) self.mediaPlayer.setVideoOutput(self.videoItem) url = QtCore.QUrl.fromLocalFile("./KakaoTalk_20210818_171950283.mp4") self.mediaPlayer.setMedia(QtMultimedia.QMediaContent(url)) # 绑定信号:媒体加载完成后调整旋转角度 self.mediaPlayer.mediaStatusChanged.connect(self.adjust_video_rotation) # 绑定信号:视频尺寸变化时自动适配窗口 self.videoItem.nativeSizeChanged.connect(self.adjust_video_scale) self.mediaPlayer.play() def adjust_video_rotation(self, status): # 等待媒体文件加载完成后读取元数据 if status != QtMultimedia.QMediaPlayer.LoadedMedia: return # 读取元数据中的旋转角度,无参数默认返回0 rotation = self.mediaPlayer.metaData().value("Rotation", 0) # 兜底逻辑:元数据无旋转参数时,判断宽高比调整 if rotation == 0: video_size = self.videoItem.nativeSize() # 竖拍视频高大于宽,默认旋转90度 if video_size.height() > video_size.width(): rotation = 90 # 设置旋转中心为视频画面中心 self.videoItem.setTransformOriginPoint(self.videoItem.boundingRect().center()) self.videoItem.setRotation(rotation) # 旋转后重新适配窗口大小 self.adjust_video_scale() def adjust_video_scale(self): if self.videoItem.nativeSize().isEmpty(): return # 保持宽高比缩放适配显示窗口 self.videoItem.setSize(self.graphicsView.size()) self.graphicsView.fitInView(self.videoItem.boundingRect(), QtCore.Qt.KeepAspectRatio) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.show() sys.exit(app.exec_())
说明
原GUI文件无需修改,代码中直接隐藏了原有的QVideoWidget控件,复用原有尺寸位置创建新的显示组件,无需调整UI结构。如果需要自定义旋转角度,直接修改adjust_video_rotation方法中的rotation值即可。
内容的提问来源于stack exchange,提问作者KimJitae
相关产品推荐
相关产品推荐

