vlc的libvlc_media_get_duration返回0的可能原因

本文探讨了使用C#与VLC库时遇到的视频时长读取为0的问题,通过排查发现该问题并非由代码引起而是视频文件本身的缺陷导致。文章提供了调试步骤与解决方案。
VLCAPI.libvlc_media_parse(libvlc_media);
IntPtr duration =  VLCAPI.libvlc_media_get_duration(libvlc_media);

代码是用C#写的,先暂停(这个是必须的,相信很多人都知道),然后调用libvlc_media_get_duration方法取得视频的总时长。

但是有时会发现返回的是0,视频能正常播放,长度是0,此时建议你用vlc的播放器把那个视频打开,看看vlc播放器下面的进度条有没有时长,如果有,那可能就是代码的问题,或者vlc的dll的问题,如果也没有,那就是视频本身的问题了……总之先用vlc播放器试试,正常了再放到程序里去调试。

当然这个有问题的视频用暴风影音还是能取到时长的,但是开发用的是vlc的库,和暴风没有任何关系了……

我之前用ffmpeg将流存为flv,最后是用杀进程的方式退出的,所以导致flv文件有点问题,就是上面说的vlc读不到时长了……

折腾了一下午,才发现不是代码的问题……

<think>我们正在讨论的是libvlc_media_player_get_state函数。这个函数用于获取当前媒体播放器的状态。根据VLC的文档,该函数返回一个libvlc_state_t枚举值,表示播放器的当前状态。 ### 函数原型 ```c libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi ); ``` ### 参数说明 - `p_mi`: 指向libvlc_media_player_t实例的指针,即媒体播放器对象。 ### 返回值(libvlc_state_t枚举) 以下是可能的状态值及其含义: | 枚举常量 | 值 | 说明 | |----------|----|------| | `libvlc_NothingSpecial` | 0 | 空闲状态,未进行任何操作 | | `libvlc_Opening` | 1 | 媒体正在打开(异步操作) | | `libvlc_Buffering` | 2 | 媒体正在缓冲(仅适用于网络流) | | `libvlc_Playing` | 3 | 媒体正在播放 | | `libvlc_Paused` | 4 | 媒体暂停 | | `libvlc_Stopped` | 5 | 媒体停止 | | `libvlc_Ended` | 6 | 媒体播放结束(到达文件末尾) | | `libvlc_Error` | 7 | 发生错误 | ### 使用示例 下面是一个简单的示例,展示如何获取媒体播放器的状态: ```c #include <stdio.h> #include <vlc/vlc.h> int main() { libvlc_instance_t *inst = libvlc_new(0, NULL); libvlc_media_t *media = libvlc_media_new_path(inst, "sample.mp4"); libvlc_media_player_t *player = libvlc_media_player_new_from_media(media); // 播放媒体 libvlc_media_player_play(player); // 等待一段时间让播放器进入播放状态(实际应用中应使用事件回调) // 这里仅作演示,使用Sleep等待(不推荐在生产环境中使用) #ifdef _WIN32 Sleep(200); #else sleep(1); #endif // 获取当前状态 libvlc_state_t state = libvlc_media_player_get_state(player); printf("当前状态: %d\n", state); // 释放资源 libvlc_media_player_stop(player); libvlc_media_player_release(player); libvlc_media_release(media); libvlc_release(inst); return 0; } ``` ### 注意事项 1. **异步特性**:媒体状态变化是异步的,因此直接调用`libvlc_media_player_get_state`可能无法立即反映最新状态(例如刚调用`play`后立即获取可能还是`Opening`状态)。 2. **事件监听**:建议通过事件管理器(`libvlc_event_manager_t`)监听状态变化事件(`libvlc_MediaPlayerStateChanged`),以实时获取状态变更。 ```c // 注册状态变化事件 libvlc_event_manager_t *em = libvlc_media_player_event_manager(player); libvlc_event_attach(em, libvlc_MediaPlayerStateChanged, state_change_cb, NULL); // 回调函数示例 static void state_change_cb(const libvlc_event_t *event, void *user_data) { libvlc_state_t new_state = (libvlc_state_t)event->u.media_player_state_changed.new_state; printf("状态变化: %d\n", new_state); } ``` 3. **错误处理**:当状态为`libvlc_Error`时,应检查错误信息(可通过日志或事件获取)以确定具体原因。 ### 状态转换图 以下是简化的状态转换流程(以播放为例): ``` NothingSpecial → Opening → Buffering (可选) → Playing Playing → Paused (暂停) → Playing (恢复) Playing → Stopped (停止) → NothingSpecial Playing → Ended (播放完成) → NothingSpecial ``` ### 常见问题 - **状态获取时机**:在调用播放操作(`play`)后立即获取状态,很可能仍然是`Opening`或`Buffering`,而不是`Playing`,因此需要等待或监听事件。 - **多线程安全**:该函数是线程安全的,可以在任何线程调用。 §§相关问题§§ 1. 如何监听 libVLC 的状态变化事件? 2. libVLC 在发生错误(`libvlc_Error`状态)时如何获取详细错误信息? 3. 媒体播放器在不同状态之间转换的典型过程是怎样的? 4. 如何判断媒体是否正在播放(包括处理缓冲状态)? </think>### `libvlc_media_player_get_state` 使用指南 `libvlc_media_player_get_state` 是 libVLC 的核心函数之一,用于获取媒体播放器的实时状态。以下是详细说明和使用方法: #### 函数原型 ```c libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi ); ``` #### 返回值含义(libvlc_state_t 枚举) | 状态常量 | 数值 | 说明 | |----------|------|------| | `libvlc_NothingSpecial` | 0 | 空闲状态(播放器已创建但未加载媒体) | | `libvlc_Opening` | 1 | 媒体正在打开(解析元数据/建立连接) | | `libvlc_Buffering` | 2 | **网络流专属**:正在缓冲数据 | | `libvlc_Playing` | 3 | 媒体正在播放 | | `libvlc_Paused` | 4 | 媒体已暂停 | | `libvlc_Stopped` | 5 | 媒体已停止(可重新播放) | | `libvlc_Ended` | 6 | 媒体播放完成(到达文件末尾) | | `libvlc_Error` | 7 | **关键状态**:发生错误(需错误处理) | #### 基础使用示例 ```c #include <vlc/vlc.h> int main() { // 初始化 libvlc_instance_t *inst = libvlc_new(0, NULL); libvlc_media_t *media = libvlc_media_new_path(inst, "video.mp4"); libvlc_media_player_t *player = libvlc_media_player_new_from_media(media); // 获取状态 libvlc_state_t state = libvlc_media_player_get_state(player); // 状态判断 if(state == libvlc_Playing) { printf("正在播放\n"); } else if(state == libvlc_Error) { printf("播放错误\n"); } // 释放资源(略) } ``` #### 高级用法:事件监听(推荐) ```c // 注册状态变化监听 libvlc_event_manager_t* em = libvlc_media_player_event_manager(player); libvlc_event_attach(em, libvlc_MediaPlayerStateChanged, state_change_cb, NULL); // 状态变化回调函数 static void state_change_cb(const libvlc_event_t* event, void* data) { libvlc_state_t new_state = event->u.media_player_state_changed.new_state; switch(new_state) { case libvlc_Playing: printf("开始播放\n"); break; case libvlc_Paused: printf("已暂停\n"); break; case libvlc_Ended: printf("播放完成\n"); break; case libvlc_Error: printf("错误代码: %d\n", libvlc_media_player_get_error(player)); break; } } ``` #### 注意事项 1. **状态延迟问题** 直接调用可能返回过时状态(如刚调用`play()`后立即获取可能仍是`Opening`)。推荐使用事件监听机制[^1]。 2. **错误状态处理** 当状态为`libvlc_Error`时,需配合错误处理函数: ```c libvlc_media_player_get_error(player); // 获取错误码 libvlc_errmsg(); // 获取错误描述 ``` 3. **线程安全** 该函数是**线程安全**的,可在任何线程调用。 4. **状态转换图** ``` NothingSpecial → Opening → Buffering → Playing ↗ ↘ Paused Stopped/Ended/Error ``` 5. **特殊状态说明** - `Buffering` 仅出现在网络流媒体 - `Ended` 状态后需调用`stop()`才能重新播放 - `Opening` 状态时长取决于媒体类型(本地文件快于网络流)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值