viewer端拉流日志是這樣的:
07:19:26.263 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.283 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.298 VERBOSE sampleVideoFrameHandler(): Video Frame received. TrackId: 140092278368896, Size: 4458, Flags 3210729368
2025-06-12 07:19:26.303 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.323 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.338 VERBOSE sampleVideoFrameHandler(): Video Frame received. TrackId: 140092278368896, Size: 263, Flags 3210729368
2025-06-12 07:19:26.343 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.363 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.378 VERBOSE sampleVideoFrameHandler(): Video Frame received. TrackId: 140092278368896, Size: 314, Flags 3210729368
2025-06-12 07:19:26.383 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.403 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.418 VERBOSE sampleVideoFrameHandler(): Video Frame received. TrackId: 140092278368896, Size: 825, Flags 3210729368
2025-06-12 07:19:26.423 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.443 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.458 VERBOSE sampleVideoFrameHandler(): Video Frame received. TrackId: 140092278368896, Size: 1066, Flags 3210729368
2025-06-12 07:19:26.463 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.484 VERBOSE sampleAudioFrameHandler(): Audio Frame received. TrackId: 140092278368896, Size: 160, Flags 3210729368
2025-06-12 07:19:26.498 VERBOSE sampleVideoFrameHandler(): Video Frame received. TrackId: 140092278368896, Size: 1029, Flags 3210729368
2025-06-12
如何從這樣的拉流日志中推算出視頻幀率和音頻幀率呢?
首先要獲取足夠的樣本
比如獲取300條視頻幀日志:
grep -i 'Video Frame received' viewer_channel_index_20250612_071920_039.log | head -n 300
- 先用 grep 過濾出所有匹配行
- 再用 head -n 300 只顯示前300條結果
之后在上面命令得到的結果基礎上,過濾出每行日志前面的日期和時間,例如,2025-06-12 07:19:42.138
grep -i 'Video Frame received' viewer_channel_index_20250612_071920_039.log | head -n 300 | awk '{print $1, $2}'
- awk ‘{print $1, $2}’ 打印每行的第1和第2列,也就是日期和時間(空格分隔)
得到的結果是:
2025-06-12 07:19:38.738
2025-06-12 07:19:38.778
...
2025-06-12 07:19:50.698
計算步驟
第一幀時間:07:19:38.738
最后一幀時間:07:19:50.698
先把時間轉換成秒:
07:19:38.738 → 73600 + 1960 + 38.738 = 26378.738秒
07:19:50.698 → 73600 + 1960 + 50.698 = 26390.698秒
時間差 = 26390.698 - 26378.738 = 11.96秒
我取了 300 條時間戳,所以,幀數 = 300
幀率 = 幀數 / 時間差 = 300 / 11.96 ≈ 25.08 fps
據此推算視頻流的平均幀率大約是 25 fps。
如果視頻幀率是 25 fps(frames per second),那么每一幀之間的理論時間間隔為:
1 秒 / 25 幀 = 0.04 秒 = 40 毫秒
幀率為 25fps → 理想幀間隔是 40ms
允許波動 ±20%:
40ms * 0.8 = 32ms(下限)
40ms * 1.2 = 48ms(上限)
所以,
lower=32
upper=48
是一個 合理、寬容但不松散 的時間間隔判斷范圍,可以用來判斷是否穩定達到了 25fps。
音頻幀的日志取樣為:
07:19:38.699
07:19:38.719
07:19:38.740
07:19:38.760
07:19:38.780
07:19:38.800
...
音頻幀之間的間隔大多為 20ms 左右,所以:
1 秒 / 0.02 秒(20ms) = 50 幀每秒
音頻幀率 ≈ 50 fps
允許波動 ±20%:
20ms * 0.8 = 16ms(下限)
20ms * 1.2 = 24ms(上限)
所以,
lower=16
upper=24