使用python vlc获取基于URL的媒体对象的持续时间-无法解析

使用python vlc获取基于URL的媒体对象的持续时间-无法解析,python,libvlc,Python,Libvlc,我试图使用Python2.7PythonVLC来解析,然后从URL获取音乐曲目的持续时间。解析不起作用,播放时暂停媒体会偶尔返回-1 我知道有两种方法可以解析媒体,在使用media.get_duration()之前必须先解析。我可以解析它,也可以播放它 不管怎样,我都无法解析媒体。使用parse_with_options() 字符串“songurl”是来自Youtube或Google Play Music的歌曲的实际流式URL,与MediaPlayer配合使用非常好 我还尝试过播放媒体0.01到

我试图使用Python2.7PythonVLC来解析,然后从URL获取音乐曲目的持续时间。解析不起作用,播放时暂停媒体会偶尔返回-1

我知道有两种方法可以解析媒体,在使用
media.get_duration()
之前必须先解析。我可以解析它,也可以播放它

不管怎样,我都无法解析媒体。使用
parse_with_options()

字符串“songurl”是来自Youtube或Google Play Music的歌曲的实际流式URL,与MediaPlayer配合使用非常好

我还尝试过播放媒体0.01到0.5秒的短时间段,然后尝试获取时间,这在大部分时间都有效,但随机返回的持续时间为-1,约为10次中的1次。再次使用
media.get_duration()
返回相同的结果

我宁愿只解析这首歌而不担心播放它,但我想不出任何解析它的方法。 我已经向PythonVLCgithub提交了一份bug报告,因为我认为
MediaParsedStatus.FIXME_0L
是某种bug

更新:我明白了!这可能是我整个编程生涯中最大的痛苦(并不多)。以下是用于获取URL跟踪时间的代码:

        instance = vlc.Instance()
        media = instance.media_new(songurl)
        player = instance.media_player_new()
        player.set_media(media)
        #Start the parser
        media.parse_with_options(1,0)
        while True:
            if str(media.get_parsed_status()) == 'MediaParsedStatus.done':
                break #Might be a good idea to add a failsafe in here.
        print media.get_duration()

media.parse_with_options
是异步的。所以,您的代码并不是在等待URL的响应,而是立即继续。与所有异步方法一样,您需要接收数据已被接收的通知,然后才能继续。在本例中,它看起来像是
mediapersedchanged
事件

或者,您应该能够使用
parse()
方法,该方法是同步的,在收到元数据之前将一直阻塞。这是不推荐的(不推荐使用),因为它可能会无限期地阻塞和锁定。但这是一个选项,取决于您使用代码的目的

编辑:

如果您需要一个将事件管理器与python绑定一起使用的示例,下面是一个很好的示例:

特别是,看看罗尔夫的答案,因为他使用它的方式可能是一个很好的起点

import vlc
parseReady = 0

def ParseReceived(event):
    global parseReady
    #set a flag that your data is ready
    parseReady = 1
...
events = player.event_manager()
events.event_attach(vlc.EventType.MediaParsedChanged, ParseReceived)
...
parseReady = 0
media.parse_with_options(1, 0)
while parseReady == 0:
    #TODO: spin something to waste time

#Once the flag is set, your data is ready
print media.get_parsed_status()
print media.get_duration()

毫无疑问,有更好的方法可以做到这一点,但这是一个基本的例子。注意,根据文档,您不能从事件回调中调用vlc方法。因此,使用简单标志而不是直接在回调中调用媒体方法。

libvlc
默认情况下不会解析网络资源。您需要使用
libvlc\u media\u parse\u network

parse()
的选项调用parse,但它完全不起作用,并为我提供了相同的
mediapersedstatus。跳过了
问题。在我的一生中,我无法解释libvlc的事件侦听器是如何工作的,它似乎难以置信地过于复杂了,仅仅为了获得一个媒体曲目的持续时间。我添加了一个链接和一些使用事件管理器的代码。我没有尝试过,因此可能需要一些调整,但基本思想已经存在,并且不太难实现。为了澄清,这是通过使用
parse\u with_选项(1,0)
实现的吗?我尝试过这个方法,但一直都会出现错误
MediaParsedStatus.FIXME_0L)
,正如您所注意到的,在解析之前尝试获取媒体持续时间会导致悲伤。一个简单的方法是检查播放的
状态
,播放时长可用。还要注意,
持续时间可以更改。有时需要一段时间才能安定下来。因此,为了准确起见,您需要不时检查持续时间,或者将事件处理程序绑定到事件
vlc.EventType.MediaPlayerLengthChanged
-祝您好运!
import vlc
parseReady = 0

def ParseReceived(event):
    global parseReady
    #set a flag that your data is ready
    parseReady = 1
...
events = player.event_manager()
events.event_attach(vlc.EventType.MediaParsedChanged, ParseReceived)
...
parseReady = 0
media.parse_with_options(1, 0)
while parseReady == 0:
    #TODO: spin something to waste time

#Once the flag is set, your data is ready
print media.get_parsed_status()
print media.get_duration()