问题描述
我遇到了 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-python
和 pafy
播放视频,这也有效。 (见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 播放列表等)时所做的事情。