基于FFmpeg C API获取HLS流AVPacket实时时间的技术咨询
基于FFmpeg C API获取HLS流AVPacket实时时间的解决方案
1. 提取EXT-X-PROGRAM-DATE-TIME字段
FFmpeg的HLS demuxer会将m3u8中的EXT-X-PROGRAM-DATE-TIME字段解析到对应分片第一个AVPacket的metadata中,key为program_date_time。你可以通过以下代码提取并转换为实时时间戳:
// 读取到AVPacket后执行 AVDictionaryEntry *date_entry = av_dict_get(pkt->metadata, "program_date_time", NULL, 0); if (date_entry) { int64_t utc_ms; // av_parse_time会将ISO8601格式字符串转为毫秒级Unix时间戳(UTC) if (av_parse_time(&utc_ms, date_entry->value, 1) == 0) { // utc_ms即为当前分片起始的实时时间,结合packet的pts计算精确时间 double pkt_offset = (pkt->pts - pkt->stream->start_time) * av_q2d(pkt->stream->time_base); int64_t pkt_real_time = utc_ms + pkt_offset * 1000; } }
2. 从.ts文件名提取秒级Unix时间戳
FFmpeg会将当前分片的文件名存入AVPacket的metadata,key为filename。你可以提取文件名中的数字部分并转换为时间戳:
AVDictionaryEntry *filename_entry = av_dict_get(pkt->metadata, "filename", NULL, 0); if (filename_entry) { std::string filename(filename_entry->value); size_t dot_pos = filename.find('.'); if (dot_pos != std::string::npos) { std::string ts_str = filename.substr(0, dot_pos); try { time_t segment_start = std::stoll(ts_str); // 计算packet相对于分片起始的偏移(毫秒) double pkt_offset = (pkt->pts - pkt->stream->start_time) * av_q2d(pkt->stream->time_base); int64_t pkt_real_time = segment_start * 1000 + pkt_offset * 1000; } catch (const std::exception& e) { // 文件名解析失败的容错处理 } } }
3. 控制HLS预加载分片数量
你可以通过设置FFmpeg的HLS demuxer选项来限制预加载的分片数量或总时长,常用选项有:
hls_segment_count:设置最多预加载的分片数量hls_max_buffer_length:设置预加载内容的最大总时长(单位:秒)
代码示例:
AVDictionary *format_opts = nullptr; // 限制预加载最多2个分片(对应你的10秒分片,总预加载时长20秒) av_dict_set(&format_opts, "hls_segment_count", "2", 0); // 或者按时长限制:av_dict_set(&format_opts, "hls_max_buffer_length", "20", 0); // 打开HLS流时传入选项 AVFormatContext *fmt_ctx = nullptr; int ret = avformat_open_input(&fmt_ctx, "your_hls_url.m3u8", nullptr, &format_opts); av_dict_free(&format_opts); if (ret < 0) { // 打开失败处理 }
备用计算方案验证
你提到的基于起始时间和pts偏移的计算方案是可行的,注意以下几点可以提升精度:
segment_count建议通过avformat_find_stream_info后,从AVFormatContext的HLS私有数据中获取已预加载的分片数,而非硬编码segment_length可以通过流的平均帧率或分片的实际时长(从m3u8解析的EXTINF字段)校准,避免固定值误差
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

