python - QMediaContent 如何在 urllib 无法下载时显示视频?

标签 python python-3.x pyqt5 urllib qmediaplayer

我有一个 Qt 应用程序来显示来自 url 的视频,使用:

player = QMediaPlayer()
...
player.setMedia(QMediaContent(QUrl(video.url)))
...

但无法使用与 urllib.request 相同的网址下载视频,响应代码始终为 200Content-Length 为零.

from urllib.request import urlopen, Request
rq = Request(video.url)
rp = urlopen(rq)
rp.headers["Content-Length"] # always 0

当我下载失败时,Qt 如何能够显示视频?

MWE

from PyQt5.QtWidgets import QApplication
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl
from urllib.request import urlopen
import sys

class Test(QVideoWidget):
    def __init__(self, *args, **kwargs):
        QVideoWidget.__init__(self, *args, **kwargs)

        self.player = QMediaPlayer()
        self.player.setVideoOutput(self)
        self.player.mediaStatusChanged.connect(self.statusChanged)

        self.url = "https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/play/?video_id=v09044190000brfkq160bkbi3ui1oko0&line=0&ratio=540p&media_type=4&vr_type=0&improve_bitrate=0&logo_name=tiktok_m&quality_type=11&source=PackSourceEnum_AWEME_DETAIL"
        self.player.setMedia(QMediaContent(QUrl(self.url)))


    def statusChanged(self, status):
        if status == QMediaPlayer.LoadedMedia:
            self.player.play()
        elif status == QMediaPlayer.EndOfMedia:
            self.player.play()

    
    def download(self):
        rp = urlopen(self.url)
        if int(rp.headers["Content-Length"]) != 0:
            with open("test.mp4", "wb") as mp4:
                while True:
                    chunk = rp.read(1024)
                    if not chunk: break
                    mp4.write(chunk)
        else:
            raise Exception("Content-Length is Zero")



if __name__ == "__main__":
    app = QApplication(sys.argv)
    test = Test()
    test.show()
    # uncomment to download
    # test.download()
    sys.exit(app.exec_())

最佳答案

经过多次尝试,我发现您必须设置“用户代理”。 Qt 不直接处理 QMediaPlayer 请求,而是像 Linux 上的 gstreamer 这样的后端处理,这些后端设置用户代理,使其正常工作。

我还发现您不应该成为像“Mozilla/5.0 ...”这样的浏览器的用户代理,这些浏览器可能会被拒绝作为一种保护手段。

from urllib.request import Request, urlopen

# ...

class Test(QVideoWidget):
    # ...
    def download(self):
        rq = Request(self.url, headers={"user-agent": "MyApp/1.0"})
        with urlopen(rq) as rp:
            with open("test.mp4", "wb") as mp4:
                while True:
                    chunk = rp.read(1024)
                    if not chunk:
                        break
                    mp4.write(chunk)

关于python - QMediaContent 如何在 urllib 无法下载时显示视频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62646093/

相关文章:

c++ - 语言间自动编译

python - 我们如何使用均值滤波器作为自适应滤波器?

python - OAuth 在 Google OAuth2 中抛出 "missing code validator"

python - 如何将数组元组转换为字典?

python - 如何使用 python openpyxl 从 Excel 中按列名删除列

python - 升级包而不使用pip升级依赖项?

python - 类型错误 : reverse() takes exactly 2 arguments (1 given)

python - 如何隐藏QMainWindow中空的centralwidget

python - 使用 QWebEngineView 显示大于 2MB 的内容?

python - 在 raspberry-pi 中安装 QtVirtualkeyboard?