import * as FileSystem from 'expo-file-system/legacy'; import type { PlayUrlResponse } from '../services/types'; /** * 将 Bilibili DASH 响应写成 MPD 文件,返回 file:// URI 供 ExoPlayer 播放。 * 选取 id === qn 的视频流(找不到则取第一条),带宽最高的音频流。 */ export async function buildDashMpdUri(playData: PlayUrlResponse, qn: number): Promise { const xml = buildMpdXml(playData, qn); const path = `${FileSystem.cacheDirectory}bili_dash_${qn}.mpd`; await FileSystem.writeAsStringAsync(path, xml, { encoding: FileSystem.EncodingType.UTF8 }); return path; } function buildMpdXml(playData: PlayUrlResponse, qn: number): string { const dash = playData.dash!; const video = dash.video.find(v => v.id === qn) ?? dash.video[0]; const audio = dash.audio.reduce((best, a) => a.bandwidth > best.bandwidth ? a : best ); const dur = dash.duration; const vSeg = video.segment_base; const aSeg = audio.segment_base; const videoSegmentBase = vSeg ? `\n ` : ''; const audioSegmentBase = aSeg ? `\n ` : ''; return ` ${escapeXml(video.baseUrl)}${videoSegmentBase} ${escapeXml(audio.baseUrl)}${audioSegmentBase} `; } function escapeXml(s: string): string { return s .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); }