Мы используем инструмент на основе PyQt5 для обработки видео. Уже несколько дней некоторые пользователи жалуются, что инструмент показывает только черный экран вместо видео. Звук все еще работает. Нам удалось воспроизвести эту проблему с помощью небольшого скрипта:
import os
from PyQt5 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, path, parent=None):
super(MainWindow, self).__init__(parent)
video_widget = QtMultimediaWidgets.QVideoWidget()
self.setCentralWidget(video_widget)
self.player = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
self.player.setVideoOutput(video_widget)
self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(path)))
self.player.play()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
file = "<file>.MP4"
w = MainWindow(file)
w.show()
sys.exit(app.exec_())
Странно то, что все пользователи используют один и тот же рабочий стол на основе Ubuntu 18.04, но только несколько пользователей страдают от этой проблемы. Я не вижу различий в их установке, которые могут быть связаны с этой проблемой. Я обнаружил кучу связанных проблем, большинство из них устарело. Вроде проблема с gstreamer какая-то. Но я не знаю, чтобы углубиться в эту тему.
Разные конвейеры для некоторых пользователей в разных системах, но не для других пользователей, указывают на проблему с VAAPI. Все работает после отключения VAAPI по инструкции на Временный пропуск декодеров vaapi в decodebin.
Иногда бывает полезно отключить vaapi из логики автоматического подключения gstreamer, например. когда есть нерешенная проблема или когда необходимо принудительно выбрать декодер в decodebin для целей тестирования.
Стандартные возможности:
Я нашел более простой способ: определить для LIBVA_DRIVER_NAME фальшивое значение, которое заставит vaapi не инициализироваться, а, следовательно, пропустит его плагины.
Например:
LIBVA_DRIVER_NAME=fakedriver gst-launch-1.0 playbin uri=file:///tmp/file.mp4
Без него:
$ gst-launch-1.0 playbin uri=file://`pwd`/bbb-1920-1080-30.mp4
Got context from element 'vaapisink0': gst.vaapi.Display=context, gst.vaapi.Display=(GstVaapiDisplay)"\(GstVaapiDisplayGLX\)\ vaapidisplayglx0";
С env var мы видим, что вместо этого был выбран avdec_h264:
LIBVA_DRIVER_NAME=fakedriver gst-launch-1.0 playbin uri=file://`pwd`/bbb-1920-1080-30.mp4 -v
...
/GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/avdec_h264:avdec_h264-0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, level=(string)4.1, profile=(string)high, codec_data=(buffer)01640029ffe1001b67640029acca501e0089f970110000030001000003003c8f18319601000568e93b2c8b, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, parsed=(boolean)true