【问题标题】:libvlc - http stream error: local stream 1 error: Cancellation (0x8)libvlc - http 流错误:本地流 1 错误:取消 (0x8)
【发布时间】:2021-06-13 20:44:42
【问题描述】:

我遇到了 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 视频的正常链接的 libvlc(例如 youtube.com/watch?v=videoID),这给了我上述错误。 (参见 C++ 代码和日志)

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

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

Fourth 通过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++ 代码能够与普通的 YouTube 链接一起使用,而不是使用 python

【问题讨论】:

    标签: python c++ lua vlc libvlc


    【解决方案1】:

    由于 Youtube URL 与 VLC 的其他 URL 不同,因此您将 HTML URL 提供给 VLC,并且 VLC 需要解析该 HTML 页面并重建实际的 视频 URL(这是 lua 脚本所做的),您不能将 HTML URL 作为媒体直接提供给媒体播放器。

    如您所做的那样,从 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 URL(或 Vimeo、dailymotion、m3u8 播放列表等)时,这就是 VLC 应用程序在后台执行的操作。

    【讨论】:

    • 您好,非常感谢。该程序现在有效。但是我在您的代码中发现了几个错误,因此请随时编辑您的评论。 itemAtIndex() 返回 std::shared_ptr,因此获取项目应如下所示:std::shared_ptr&lt;VLC::Media&gt; video = media.subitems()-&gt;itemAtIndex(0);。因此设置媒体会分别改变:player.setMedia(*video);
    • 感谢修复,刚刚编辑了代码。我从记忆中写出来的,诚然没有运行代码:)
    猜你喜欢
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    • 2013-10-16
    • 2021-01-20
    相关资源
    最近更新 更多