From dae8df840a2b8c31f4ff2b7e24fea53c8be24788 Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:02:09 +0000 Subject: [PATCH] opt: edl file (#2455) --- lib/pages/video/controller.dart | 72 ++++++++++++--------- lib/pages/video/widgets/header_control.dart | 12 +++- lib/plugin/pl_player/controller.dart | 13 +++- 3 files changed, 63 insertions(+), 34 deletions(-) diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index 422d35b3e..dbaa832a1 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -717,9 +717,8 @@ class VideoDetailController extends GetxController bool autoFullScreenFlag = false, }) async { Duration? seek = defaultST ?? playedTime; - if (seek == null || seek == Duration.zero) { - seek = getFirstSegment(); - } + if (seek == .zero) seek = null; + seek ??= getFirstSegment(); await plPlayerController.setDataSource( isFileSource ? FileSource( @@ -858,36 +857,49 @@ class VideoDetailController extends GetxController displayTime: const Duration(seconds: 3), ); } - if (data.dash == null && data.durl != null) { - final first = data.durl!.first; - videoUrl = VideoUtils.getCdnUrl(first.playUrls); - audioUrl = ''; - - // 实际为FLV/MP4格式,但已被淘汰,这里仅做兜底处理 - final videoQuality = VideoQuality.fromCode(data.quality!); - firstVideo = VideoItem( - id: data.quality!, - baseUrl: videoUrl, - codecs: 'avc1', - quality: videoQuality, - ); - _setVideoHeight(); - currentDecodeFormats = VideoDecodeFormatType.AVC; - currentVideoQa.value = videoQuality; - await _initPlayerIfNeeded(autoFullScreenFlag); - isQuerying = false; - return; - } if (data.dash == null) { - SmartDialog.showToast('视频资源不存在'); - _autoPlay.value = false; - videoState.value = false; - if (plPlayerController.isFullScreen.value) { - plPlayerController.triggerFullScreen(status: false); + if (data.durl case final durl?) { + // it will cause all files to be opened simultaneously + if (durl.length > 1) { + // TODO: refa + final sb = StringBuffer('edl://!no_clip;!no_chapters;'); + for (var i in durl) { + final video = VideoUtils.getCdnUrl(i.playUrls); + sb.write('%${video.length}%$video,length=${i.length! / 1000};'); + } + videoUrl = sb.toString(); + } else { + videoUrl = VideoUtils.getCdnUrl(durl.single.playUrls); + } + + audioUrl = ''; + + // 实际为FLV/MP4格式,但已被淘汰,这里仅做兜底处理 + final videoQuality = VideoQuality.fromCode(data.quality!); + firstVideo = VideoItem( + id: data.quality!, + baseUrl: videoUrl, + codecs: 'avc1', + quality: videoQuality, + ); + _setVideoHeight(); + currentDecodeFormats = VideoDecodeFormatType.AVC; + currentVideoQa.value = videoQuality; + await _initPlayerIfNeeded(autoFullScreenFlag); + isQuerying = false; + return; + } else { + SmartDialog.showToast('视频资源不存在'); + _autoPlay.value = false; + videoState.value = false; + if (plPlayerController.isFullScreen.value) { + plPlayerController.triggerFullScreen(status: false); + } + isQuerying = false; + return; } - isQuerying = false; - return; } + final List videoList = data.dash!.video!; // if (kDebugMode) debugPrint("allVideosList:${allVideosList}"); // 当前可播放的最高质量视频 diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index bc9b78dea..be1eed0c9 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -572,7 +572,17 @@ class HeaderControlState extends State onTap: () { plPlayerController.onlyPlayAudio.value = !onlyPlayAudio; - widget.videoDetailCtr.playerInit(); + final player = + plPlayerController.videoPlayerController!; + if (onlyPlayAudio && + player.state.tracks.video.length <= 2) { + videoDetailCtr.playerInit(); + } else { + player.setProperty( + 'file-local-options/vid', + onlyPlayAudio ? 'auto' : 'no', + ); + } }, text: " 听视频 ", selectStatus: onlyPlayAudio, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 154ed669f..ec8d50ece 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -1,5 +1,5 @@ import 'dart:async' show StreamSubscription, Timer; -import 'dart:convert' show ascii; +import 'dart:convert' show ascii, utf8; import 'dart:io' show Platform; import 'dart:math' show max, min; import 'dart:ui' as ui; @@ -816,8 +816,15 @@ class PlPlayerController with BlockConfigMixin { if (onlyPlayAudio.value) { video = audio; } else { - extras['audio-files'] = - '"${Platform.isWindows ? audio.replaceAll(';', r'\;') : audio.replaceAll(':', r'\:')}"'; + // dely_open need provide length + video = + ('edl://' + '!no_clip;!no_chapters;' + // '!delay_open,media_type=video;' + '%${isFileSource ? utf8.encode(video).length : video.length}%$video;' + '!new_stream;!no_clip;!no_chapters;' + // '!delay_open,media_type=audio;' + '%${isFileSource ? utf8.encode(audio).length : audio.length}%$audio'); } if (enableAudioNormalization) { final String audioNormalization;