You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android ExoPlayer:获取直播流的当前时间

获取ExoPlayer中RTMP直播的实际时间

嘿,这个问题我之前做直播项目的时候也碰到过——ExoPlayer的getCurrentPosition()对直播流来说,确实只会返回你开始播放后的相对时长,而不是直播内容对应的实际时间。不过别担心,只要你的RTMP流本身携带了时间戳信息,还是有办法拿到实际时间的,下面给你两种可行的方案:

方案一:通过ExoPlayer的Timeline获取直播时间

ExoPlayer的Timeline对象会存储直播流的关键时间信息,我们可以通过监听时间线变化来提取实际直播时间:

  1. 给Player注册一个Listener,监听时间线变更事件
  2. 在回调中获取当前直播窗口的presentationStartTimeMs(这是直播流的起始UTC时间戳,单位毫秒)
  3. 用这个起始时间加上getCurrentPosition()返回的相对时长,就能得到当前直播内容的实际时间
player.addListener(new Player.Listener() {
    @Override
    public void onTimelineChanged(Timeline timeline, int reason) {
        super.onTimelineChanged(timeline, reason);
        Window currentWindow = new Window();
        // 获取当前播放窗口的信息
        timeline.getWindow(player.getCurrentWindowIndex(), currentWindow);
        
        if (currentWindow.isLive()) {
            long presentationStartTimeMs = currentWindow.getPresentationStartTimeMs();
            // 检查服务器是否提供了有效起始时间
            if (presentationStartTimeMs != C.TIME_UNSET) {
                // 计算实际直播时间:起始时间 + 相对播放时长
                long actualLiveTimeMs = presentationStartTimeMs + player.getCurrentPosition();
                // 转换成可读的日期格式
                Date actualLiveTime = new Date(actualLiveTimeMs);
                // 这里就可以使用actualLiveTime了,比如显示给用户或者做业务逻辑处理
            }
        }
    }
});

注意:这个方法的前提是你的RTMP服务器已经正确传递了直播的起始时间戳,如果服务器没提供,presentationStartTimeMs会返回C.TIME_UNSET,这种情况下就没法用这个方法了

方案二:监听RTMP流的元数据获取时间

有些RTMP服务器会在流的元数据中携带当前直播的时间戳,我们可以通过ExoPlayer的MetadataOutput来监听这些元数据:

  1. 创建一个MetadataOutput实例,实现onMetadata回调来解析元数据中的时间信息
  2. 在创建RTMP MediaSource时,将这个MetadataOutput添加进去
// 创建元数据监听器
MetadataOutput metadataOutput = new MetadataOutput() {
    @Override
    public void onMetadata(Metadata metadata) {
        // 遍历所有元数据条目,查找时间相关字段
        for (int i = 0; i < metadata.length(); i++) {
            Metadata.Entry entry = metadata.get(i);
            // 这里以ID3格式的TIMESTAMP字段为例,不同服务器可能用不同格式
            if (entry instanceof TextInformationFrame) {
                TextInformationFrame id3Frame = (TextInformationFrame) entry;
                if ("TIMESTAMP".equals(id3Frame.id)) {
                    try {
                        // 将元数据中的时间字符串转换成毫秒时间戳
                        long actualTimeMs = Long.parseLong(id3Frame.value);
                        Date actualLiveTime = new Date(actualTimeMs);
                        // 处理获取到的实际时间
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 如果是AMF格式的元数据,需要做对应的解析逻辑
        }
    }
};

// 创建RTMP MediaSource并添加元数据监听器
RtmpMediaSource.Factory rtmpFactory = new RtmpMediaSource.Factory();
MediaItem mediaItem = MediaItem.fromUri("你的RTMP流地址");
RtmpMediaSource mediaSource = (RtmpMediaSource) rtmpFactory.createMediaSource(mediaItem);
mediaSource.addMetadataOutput(metadataOutput);

// 将MediaSource设置给Player
player.setMediaSource(mediaSource);

注意:这个方法完全依赖于RTMP服务器的配置——只有服务器主动发送包含时间戳的元数据,客户端才能拿到。不同服务器的元数据格式可能不同,你需要和服务器开发人员确认时间字段的名称和格式

最后提醒

如果以上两种方法都没法拿到实际时间,大概率是你的RTMP服务器没有传递任何时间相关的信息。这种情况下,客户端是无法获取到直播的实际时间的,需要先调整服务器的配置,让它在流中携带时间戳信息。

内容的提问来源于stack exchange,提问作者Rohan M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:57:36