libvlc - http 流错误:本地流 1 错误:取消 (0x8)

问题描述

我遇到了 libvlc错误,尝试播放来自 YouTube 的视频导致错误 http stream error: local stream 1 error: Cancellation (0x8)

背景

C++ 代码

#include <iostream>
#include <thread>
#include <vlc/vlc.h>
#include <vlc/libvlc.h>
#include <vlcpp/vlc.hpp>

int main() {
    const char *const arg[] = { "--no-video","-vv" };
    VLC::Instance instance = VLC::Instance(2,arg);
    
    const std::string mrl = "link to youtube video here";
    VLC::Media media = VLC::Media(instance,mrl,VLC::Media::FromLocation);
    
    VLC::MediaPlayer player = VLC::MediaPlayer(instance);
    player.setMedia(media);
    
    player.play();
    
    std::this_thread::sleep_for( std::chrono::seconds(215) );
    
    return 0;
}

C++ 日志: https://gist.github.com/trofchik/39ebc5df6aeb4a82b464db74a48846d7

VLC 播放器应用日志: https://gist.github.com/trofchik/8028fda99c08f22523800a03f26e168c 请注意,由于 youtube api 的一些怪癖,我将 720p 设置为播放视频的首选分辨率。

Python 代码

#!/usr/bin/python3

import pafy 
import vlc
import time
import youtube_dl

url = 'link to youtube video here'

song = pafy.new(url)
duration = song.length
audiostreams = song.audiostreams
best = song.getbest()
play_url = best.url

print(play_url)

instance = vlc.Instance('--no-video')

player = instance.media_player_new()
media = instance.media_new(play_url)
media.get_mrl()
player.set_media(media)

player.play()
time.sleep(duration)

Python 日志: https://gist.github.com/trofchik/68e797339853dd5607d8c7b3fcb1493a

使用 python 脚本生成链接时的 C++ 日志: https://gist.github.com/trofchik/000a32280ba177a3e8897eb25cc7b9e0

我还用在 vlc 的 github 页面上找到的代码替换了 youtube 视频的 lua 脚本代码,您可以在此处找到:https://github.com/videolan/vlc/blob/master/share/lua/playlist/youtube.lua 该脚本显然为视频播放生成了正确的 url。

说明

我尝试用 3 种不同的方式播放视频。

首先使用带有指向 youtube 视频(例如 youtube.com/watch?v=videoID)的正常链接的 libvlc,这给了我上述错误。 (见 C++ 代码和日志)

其次是使用运行良好的 VLC 播放器应用程序播放。 (见 VLC 播放器应用日志)

第三是使用 vlc-pythonpafy 播放视频,这也有效。 (见python代码和日志)

第四是通过 libvlc 播放它,但使用由 python 代码(存储在 play_url 变量中)生成链接,该链接有效。 (使用 python 生成链接时,请参阅 C++ 代码和 C++ 日志)有趣的是,在 C++ 日志中,当在第 301 行使用普通链接时,您可以看到该链接的格式与由 python 代码生成链接格式相似。该程序仍然不起作用。奇怪的是,如果我使用由 libvlc 生成链接(我在上面指向并以“r1--”开头的链接),程序将按预期运行。

到目前为止我做了什么,我想要什么?

我所做的大部分事情我已经在上面描述过了。除此之外,我花了几个小时比较了我用来播放视频的所有 4 种方法的日志,但没有发现任何可以指向我修复的方法。我也在网上搜索了修复。许多人建议将最大播放分辨率设置为 720p,这是我在使用 VLC 播放器应用程序时所做的。我怀疑认分辨率是问题所在,因为我总是使用 --no-video 参数运行代码,该参数会禁用视频输出并仅保留音频。

编辑:尝试使用 --prefered-resolution=720 参数运行 C++ 代码。没用。在上述第四种情况下,没有任何变化。

我认为将 python 与 libvlc 结合使用是最后的手段,而是找出 lua 本地使用的 libvlc 的问题。因此,我希望我的 C++ 代码能够在不使用 python 的情况下使用正常的 YouTube 链接

解决方法

由于 Youtube URL 与 VLC 的其他 URL 不同,从某种意义上说,您将一个 HTML URL 提供给 VLC,并且 VLC 需要解析该 HTML 页面并重建实际的视频 URL(这是 lua 脚本所做的),您不能将 HTML URL 作为媒体直接提供给 mediaplayer。

如您所做的那样,从 HTML URL 创建媒体。

VLC::Media media = VLC::Media(instance,mrl,VLC::Media::FromLocation);

解析它。

media.parseWithOptions(VLC::Media::ParseFlags::Network,-1);

解析是异步完成的。媒体上有一个活动可以告诉您何时结束。

成功解析后,您可以从媒体子项(通常是媒体列表中的第一项)访问实际视频 URL,并将其提供给媒体播放器。

std::shared_ptr<VLC::Media> video = media.subitems()->itemAtIndex(0);
player.setMedia(*video);
player.play();

这就是 VLC 应用在检测到视频是 YouTube 网址(或 Vimeo、dailymotion、m3u8 播放列表等)时所做的事情。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...