测速增加码率计算
This commit is contained in:
@@ -1140,7 +1140,7 @@ function PlayPageClient() {
|
|||||||
|
|
||||||
// 保存优选时的测速结果,避免EpisodeSelector重复测速
|
// 保存优选时的测速结果,避免EpisodeSelector重复测速
|
||||||
const [precomputedVideoInfo, setPrecomputedVideoInfo] = useState<
|
const [precomputedVideoInfo, setPrecomputedVideoInfo] = useState<
|
||||||
Map<string, { quality: string; loadSpeed: string; pingTime: number }>
|
Map<string, { quality: string; loadSpeed: string; pingTime: number; bitrate: string }>
|
||||||
>(new Map());
|
>(new Map());
|
||||||
|
|
||||||
// 折叠状态(仅在 lg 及以上屏幕有效)
|
// 折叠状态(仅在 lg 及以上屏幕有效)
|
||||||
@@ -1238,7 +1238,7 @@ function PlayPageClient() {
|
|||||||
const batchSize = Math.ceil(sources.length / 2);
|
const batchSize = Math.ceil(sources.length / 2);
|
||||||
const allResults: Array<{
|
const allResults: Array<{
|
||||||
source: SearchResult;
|
source: SearchResult;
|
||||||
testResult: { quality: string; loadSpeed: string; pingTime: number };
|
testResult: { quality: string; loadSpeed: string; pingTime: number; bitrate: string };
|
||||||
} | null> = [];
|
} | null> = [];
|
||||||
|
|
||||||
for (let start = 0; start < sources.length; start += batchSize) {
|
for (let start = 0; start < sources.length; start += batchSize) {
|
||||||
@@ -1278,6 +1278,7 @@ function PlayPageClient() {
|
|||||||
quality: string;
|
quality: string;
|
||||||
loadSpeed: string;
|
loadSpeed: string;
|
||||||
pingTime: number;
|
pingTime: number;
|
||||||
|
bitrate: string;
|
||||||
hasError?: boolean;
|
hasError?: boolean;
|
||||||
}
|
}
|
||||||
>();
|
>();
|
||||||
@@ -1294,7 +1295,7 @@ function PlayPageClient() {
|
|||||||
// 过滤出成功的结果用于优选计算
|
// 过滤出成功的结果用于优选计算
|
||||||
const successfulResults = allResults.filter(Boolean) as Array<{
|
const successfulResults = allResults.filter(Boolean) as Array<{
|
||||||
source: SearchResult;
|
source: SearchResult;
|
||||||
testResult: { quality: string; loadSpeed: string; pingTime: number };
|
testResult: { quality: string; loadSpeed: string; pingTime: number; bitrate: string };
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
setPrecomputedVideoInfo(newVideoInfoMap);
|
setPrecomputedVideoInfo(newVideoInfoMap);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface VideoInfo {
|
|||||||
quality: string;
|
quality: string;
|
||||||
loadSpeed: string;
|
loadSpeed: string;
|
||||||
pingTime: number;
|
pingTime: number;
|
||||||
|
bitrate: string; // 视频码率
|
||||||
hasError?: boolean; // 添加错误状态标识
|
hasError?: boolean; // 添加错误状态标识
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -898,6 +899,11 @@ const EpisodeSelector: React.FC<EpisodeSelectorProps> = ({
|
|||||||
<div className='text-orange-600 dark:text-orange-400 font-medium text-xs'>
|
<div className='text-orange-600 dark:text-orange-400 font-medium text-xs'>
|
||||||
{videoInfo.pingTime}ms
|
{videoInfo.pingTime}ms
|
||||||
</div>
|
</div>
|
||||||
|
{videoInfo.bitrate && videoInfo.bitrate !== '未知' && (
|
||||||
|
<div className='text-purple-600 dark:text-purple-400 font-medium text-xs'>
|
||||||
|
{videoInfo.bitrate}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+30
-1
@@ -135,12 +135,13 @@ export function processVideoUrl(originalUrl: string): string {
|
|||||||
/**
|
/**
|
||||||
* 从m3u8地址获取视频质量等级和网络信息
|
* 从m3u8地址获取视频质量等级和网络信息
|
||||||
* @param m3u8Url m3u8播放列表的URL
|
* @param m3u8Url m3u8播放列表的URL
|
||||||
* @returns Promise<{quality: string, loadSpeed: string, pingTime: number}> 视频质量等级和网络信息
|
* @returns Promise<{quality: string, loadSpeed: string, pingTime: number, bitrate: string}> 视频质量等级和网络信息
|
||||||
*/
|
*/
|
||||||
export async function getVideoResolutionFromM3u8(m3u8Url: string): Promise<{
|
export async function getVideoResolutionFromM3u8(m3u8Url: string): Promise<{
|
||||||
quality: string; // 如720p、1080p等
|
quality: string; // 如720p、1080p等
|
||||||
loadSpeed: string; // 自动转换为KB/s或MB/s
|
loadSpeed: string; // 自动转换为KB/s或MB/s
|
||||||
pingTime: number; // 网络延迟(毫秒)
|
pingTime: number; // 网络延迟(毫秒)
|
||||||
|
bitrate: string; // 视频码率(如 "2.5 Mbps")
|
||||||
}> {
|
}> {
|
||||||
try {
|
try {
|
||||||
// 直接使用m3u8 URL作为视频源,避免CORS问题
|
// 直接使用m3u8 URL作为视频源,避免CORS问题
|
||||||
@@ -182,6 +183,7 @@ export async function getVideoResolutionFromM3u8(m3u8Url: string): Promise<{
|
|||||||
let actualLoadSpeed = '未知';
|
let actualLoadSpeed = '未知';
|
||||||
let hasSpeedCalculated = false;
|
let hasSpeedCalculated = false;
|
||||||
let hasMetadataLoaded = false;
|
let hasMetadataLoaded = false;
|
||||||
|
let estimatedBitrate = 0; // 估算的码率(bps)
|
||||||
|
|
||||||
let fragmentStartTime = 0;
|
let fragmentStartTime = 0;
|
||||||
|
|
||||||
@@ -211,17 +213,32 @@ export async function getVideoResolutionFromM3u8(m3u8Url: string): Promise<{
|
|||||||
? '480p'
|
? '480p'
|
||||||
: 'SD'; // 480p: 854x480
|
: 'SD'; // 480p: 854x480
|
||||||
|
|
||||||
|
// 格式化码率
|
||||||
|
const bitrateStr = estimatedBitrate > 0
|
||||||
|
? estimatedBitrate >= 1000000
|
||||||
|
? `${(estimatedBitrate / 1000000).toFixed(1)} Mbps`
|
||||||
|
: `${Math.round(estimatedBitrate / 1000)} Kbps`
|
||||||
|
: '未知';
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
quality,
|
quality,
|
||||||
loadSpeed: actualLoadSpeed,
|
loadSpeed: actualLoadSpeed,
|
||||||
pingTime: Math.round(pingTime),
|
pingTime: Math.round(pingTime),
|
||||||
|
bitrate: bitrateStr,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// webkit 无法获取尺寸,直接返回
|
// webkit 无法获取尺寸,直接返回
|
||||||
|
const bitrateStr = estimatedBitrate > 0
|
||||||
|
? estimatedBitrate >= 1000000
|
||||||
|
? `${(estimatedBitrate / 1000000).toFixed(1)} Mbps`
|
||||||
|
: `${Math.round(estimatedBitrate / 1000)} Kbps`
|
||||||
|
: '未知';
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
quality: '未知',
|
quality: '未知',
|
||||||
loadSpeed: actualLoadSpeed,
|
loadSpeed: actualLoadSpeed,
|
||||||
pingTime: Math.round(pingTime),
|
pingTime: Math.round(pingTime),
|
||||||
|
bitrate: bitrateStr,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,6 +272,18 @@ export async function getVideoResolutionFromM3u8(m3u8Url: string): Promise<{
|
|||||||
actualLoadSpeed = `${avgSpeedKBps.toFixed(1)} KB/s`;
|
actualLoadSpeed = `${avgSpeedKBps.toFixed(1)} KB/s`;
|
||||||
}
|
}
|
||||||
hasSpeedCalculated = true;
|
hasSpeedCalculated = true;
|
||||||
|
|
||||||
|
// 从分片估算码率
|
||||||
|
if (data.frag && data.frag.duration > 0) {
|
||||||
|
const fragmentDuration = data.frag.duration; // 分片时长(秒)
|
||||||
|
const fragmentSize = size; // 分片大小(字节)
|
||||||
|
|
||||||
|
// 码率 = (分片大小 × 8 bits) / 分片时长
|
||||||
|
estimatedBitrate = Math.round((fragmentSize * 8) / fragmentDuration);
|
||||||
|
|
||||||
|
console.log(`[测速] 估算码率: ${(estimatedBitrate / 1000000).toFixed(2)} Mbps (分片: ${(fragmentSize / 1024 / 1024).toFixed(2)} MB, 时长: ${fragmentDuration.toFixed(1)}s)`);
|
||||||
|
}
|
||||||
|
|
||||||
checkAndResolve(); // 尝试返回结果
|
checkAndResolve(); // 尝试返回结果
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user