试试这个直接解析文件结构吧
如果 TS 文件是直播切片,有的包可能缺少完整 PTS(比如只有视频或音频片段)。
如果 TS 文件非常小(不足一帧),可能返回 null。
对 H.265 流也有效(PES 格式相同)。
[JavaScript] 纯文本查看 复制代码 const fs = require("fs");
function extractPTS(buf) {
if (buf.length < 5) return null;
if ((buf[0] & 0xF0) !== 0x20 && (buf[0] & 0xF0) !== 0x30) return null;
const pts =
((buf[0] & 0x0E) << 29) |
((buf[1] & 0xFF) << 22) |
((buf[2] & 0xFE) << 14) |
((buf[3] & 0xFF) << 7) |
((buf[4] & 0xFE) >> 1);
return pts >>> 0;
}
function getTsDuration(filePath) {
const fd = fs.openSync(filePath, "r");
const packetSize = 188;
const buffer = Buffer.alloc(packetSize);
let firstPTS = null;
let lastPTS = null;
let bytesRead;
while ((bytesRead = fs.readSync(fd, buffer, 0, packetSize, null)) === packetSize) {
if (buffer[0] !== 0x47) continue;
const adaptationFieldControl = (buffer[3] >> 4) & 0x3;
const hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;
if (!hasPayload) continue;
let payloadStart = 4;
if (adaptationFieldControl === 3) {
const adaptationLength = buffer[4];
payloadStart += 1 + adaptationLength;
if (payloadStart >= packetSize) continue;
}
if (
buffer[payloadStart] === 0x00 &&
buffer[payloadStart + 1] === 0x00 &&
buffer[payloadStart + 2] === 0x01
) {
const streamId = buffer[payloadStart + 3];
if (streamId >= 0xe0 && streamId <= 0xef) {
const headerDataLength = buffer[payloadStart + 8];
const ptsData = buffer.subarray(payloadStart + 9, payloadStart + 14);
const pts = extractPTS(ptsData);
if (pts != null) {
if (firstPTS == null) firstPTS = pts;
lastPTS = pts;
}
}
}
}
fs.closeSync(fd);
if (firstPTS == null || lastPTS == null) {
console.log("未能解析到 PTS");
return null;
}
if (lastPTS < firstPTS) lastPTS += 2 ** 33;
const durationSec = (lastPTS - firstPTS) / 90000;
return durationSec;
}
const file = "video.ts";
const duration = getTsDuration(file);
if (duration != null) {
console.log(`时长:${duration.toFixed(2)} 秒`);
} else {
console.log("未能解析出时长");
}
补充内容 (2025-10-23 14:50):
这个是nodejs代码,需要自己转换成易语言 |