feat: millisecond skip (#869)

* feat: millisecond skip

* fix: formatDuration

* fix: post segment
This commit is contained in:
My-Responsitories
2025-06-11 09:39:26 +08:00
committed by GitHub
parent bc2de4828b
commit 3655c31a48
6 changed files with 41 additions and 45 deletions

View File

@@ -10,11 +10,11 @@ class SegmentModel {
required this.segmentType,
required this.segment,
required this.skipType,
this.hasSkipped,
this.hasSkipped = false,
});
String UUID;
SegmentType segmentType;
Pair<int, int> segment;
SkipType skipType;
bool? hasSkipped;
bool hasSkipped;
}

View File

@@ -1,18 +1,18 @@
class SegmentItemModel {
String cid;
String? cid;
String category;
String actionType;
String? actionType;
List<int> segment;
String uuid;
double videoDuration;
num? videoDuration;
SegmentItemModel({
required this.cid,
this.cid,
required this.category,
required this.actionType,
this.actionType,
required this.segment,
required this.uuid,
required this.videoDuration,
this.videoDuration,
});
factory SegmentItemModel.fromJson(Map<String, dynamic> json) =>
@@ -20,9 +20,12 @@ class SegmentItemModel {
cid: json["cid"],
category: json["category"],
actionType: json["actionType"],
segment:
(json["segment"] as List).map((e) => (e as num).round()).toList(),
segment: (json["segment"] as List)
.map((e) => ((e as num) * 1000).round())
.toList(),
uuid: json["UUID"],
videoDuration: (json["videoDuration"] as num).toDouble(),
videoDuration: json["videoDuration"] == null
? null
: (json["videoDuration"] as num) * 1000,
);
}

View File

@@ -611,7 +611,7 @@ class VideoDetailController extends GetxController
),
contentPadding: const EdgeInsets.only(left: 16, right: 8),
subtitle: Text(
'${Utils.formatDuration(item.segment.first)}${Utils.formatDuration(item.segment.second)}',
'${Utils.formatDuration(item.segment.first / 1000)}${Utils.formatDuration(item.segment.second / 1000)}',
style: const TextStyle(fontSize: 13),
),
trailing: Row(
@@ -696,7 +696,8 @@ class VideoDetailController extends GetxController
void handleSBData(List<SegmentItemModel> list) {
if (list.isNotEmpty) {
try {
double duration = list.first.videoDuration;
final duration = list.first.videoDuration ??
plPlayerController.duration.value.inMilliseconds;
// segmentList
segmentList.addAll(list
.where((item) =>
@@ -704,13 +705,12 @@ class VideoDetailController extends GetxController
item.segment[1] >= item.segment[0])
.map(
(item) {
SegmentType segmentType = SegmentType
.values[plPlayerController.segmentTypes.indexOf(item.category)];
final segmentType = SegmentType.values.byName(item.category);
if (item.segment[0] == 0 && item.segment[1] == 0) {
videoLabel.value +=
'${videoLabel.value.isNotEmpty ? '/' : ''}${segmentType.title}';
}
SkipType skipType =
var skipType =
plPlayerController.blockSettings[segmentType.index].second;
if (skipType != SkipType.showOnly) {
if (item.segment[1] == item.segment[0] ||
@@ -733,7 +733,7 @@ class VideoDetailController extends GetxController
if (positionSubscription == null &&
!isShowCover.value &&
plPlayerController.videoPlayerController != null) {
final currPost = plPlayerController.position.value.inSeconds;
final currPost = plPlayerController.position.value.inMilliseconds;
if (currPost > segmentModel.segment.first &&
currPost < segmentModel.segment.second) {
if (segmentModel.skipType == SkipType.alwaysSkip) {
@@ -760,8 +760,7 @@ class VideoDetailController extends GetxController
).toList());
// _segmentProgressList
segmentProgressList ??= <Segment>[];
segmentProgressList!.addAll(segmentList.map((e) {
(segmentProgressList ??= <Segment>[]).addAll(segmentList.map((e) {
double start = (e.segment.first / duration).clamp(0.0, 1.0);
double end = (e.segment.second / duration).clamp(0.0, 1.0);
return Segment(start, end, _getColor(e.segmentType));
@@ -790,16 +789,18 @@ class VideoDetailController extends GetxController
int currentPos = position.inSeconds;
if (currentPos != _lastPos) {
_lastPos = currentPos;
final msPos = currentPos * 1000;
for (SegmentModel item in segmentList) {
// if (kDebugMode) {
// debugPrint(
// '${position.inSeconds},,${item.segment.first},,${item.segment.second},,${item.skipType.name},,${item.hasSkipped}');
// }
if (item.segment.first == position.inSeconds) {
if (msPos <= item.segment.first &&
item.segment.first <= msPos + 1000) {
if (item.skipType == SkipType.alwaysSkip) {
onSkip(item);
} else if (item.skipType == SkipType.skipOnce &&
item.hasSkipped != true) {
item.hasSkipped) {
item.hasSkipped = true;
onSkip(item);
} else if (item.skipType == SkipType.skipManually) {
@@ -905,7 +906,7 @@ class VideoDetailController extends GetxController
try {
plPlayerController.danmakuController?.clear();
await plPlayerController.videoPlayerController
?.seek(Duration(seconds: item.segment.second));
?.seek(Duration(milliseconds: item.segment.second));
if (isSkip) {
if (GStorage.blockToast) {
_showBlockToast('已跳过${item.segmentType.shortTitle}片段');

View File

@@ -325,8 +325,8 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
int start = max(
0,
(list![index].segment.first * 1000)
.toInt() -
2,
.round() -
2000,
);
await widget
.plPlayerController.videoPlayerController!
@@ -349,7 +349,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
Duration(
milliseconds:
(list![index].segment.second * 1000)
.toInt(),
.round(),
),
);
}

View File

@@ -300,12 +300,10 @@ class PlPlayerController {
late final List<Pair<SegmentType, SkipType>> blockSettings =
GStorage.blockSettings;
late final List<Color> blockColor = GStorage.blockColor;
late final List<String> segmentTypes =
SegmentType.values.map((item) => item.name).toList();
late final List<String> enableList = blockSettings
late final Set<String> enableList = blockSettings
.where((item) => item.second != SkipType.disable)
.map((item) => item.first.name)
.toList();
.toSet();
late final blockServer = GStorage.blockServer;
// settings

View File

@@ -455,22 +455,16 @@ class Utils {
}
static String formatDuration(num seconds) {
int hours = seconds ~/ 3600;
int minutes = (seconds % 3600) ~/ 60;
num remainingSeconds = seconds % 60;
if (remainingSeconds is double) {
remainingSeconds = remainingSeconds.toPrecision(3);
}
String minutesStr = minutes.toString().padLeft(2, '0');
String secondsStr = remainingSeconds.toString().padLeft(2, '0');
if (hours > 0) {
String hoursStr = hours.toString().padLeft(2, '0');
return "$hoursStr:$minutesStr:$secondsStr";
} else {
return "$minutesStr:$secondsStr";
}
int h = seconds ~/ 3600;
seconds %= 3600;
int m = seconds ~/ 60;
seconds %= 60;
String sms = seconds is double
? seconds.toStringAsFixed(3).padLeft(6, '0')
: seconds.toString().padLeft(2, '0');
return h == 0
? "${m.toString().padLeft(2, '0')}:$sms"
: "${h.toString().padLeft(2, '0')}:${m.toString().padLeft(2, '0')}:$sms";
}
static int duration(String duration) {