mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 03:06:59 +08:00
opt: PlPlayerController (#1832)
* opt: audio uri * opt: PlPlayerController
This commit is contained in:
committed by
GitHub
parent
ed2bd069ee
commit
9411785d26
@@ -83,18 +83,17 @@ class PlPlayerController with BlockConfigMixin {
|
||||
/// 响应数据
|
||||
/// 带有Seconds的变量只在秒数更新时更新,以避免频繁触发重绘
|
||||
// 播放位置
|
||||
final Rx<Duration> position = Rx(Duration.zero);
|
||||
Duration position = Duration.zero;
|
||||
final RxInt positionSeconds = 0.obs;
|
||||
|
||||
/// 进度条位置
|
||||
final Rx<Duration> sliderPosition = Rx(Duration.zero);
|
||||
Duration sliderPosition = Duration.zero;
|
||||
final RxInt sliderPositionSeconds = 0.obs;
|
||||
// 展示使用
|
||||
final Rx<Duration> sliderTempPosition = Rx(Duration.zero);
|
||||
|
||||
/// 视频时长
|
||||
final Rx<Duration> duration = Rx(Duration.zero);
|
||||
final Rx<Duration> durationSeconds = Duration.zero.obs;
|
||||
|
||||
/// 视频缓冲
|
||||
final Rx<Duration> buffered = Rx(Duration.zero);
|
||||
@@ -118,9 +117,6 @@ class PlPlayerController with BlockConfigMixin {
|
||||
/// 是否展示控制条
|
||||
final RxBool showControls = false.obs;
|
||||
|
||||
/// 音量控制条展示/隐藏
|
||||
final RxBool showVolumeStatus = false.obs;
|
||||
|
||||
/// 亮度控制条展示/隐藏
|
||||
final RxBool showBrightnessStatus = false.obs;
|
||||
|
||||
@@ -182,7 +178,6 @@ class PlPlayerController with BlockConfigMixin {
|
||||
|
||||
Timer? _timer;
|
||||
Timer? _timerForSeek;
|
||||
Timer? _timerForShowingVolume;
|
||||
|
||||
Box setting = GStorage.setting;
|
||||
|
||||
@@ -460,25 +455,19 @@ class PlPlayerController with BlockConfigMixin {
|
||||
}
|
||||
|
||||
void updateSliderPositionSecond() {
|
||||
int newSecond = sliderPosition.value.inSeconds;
|
||||
int newSecond = sliderPosition.inSeconds;
|
||||
if (sliderPositionSeconds.value != newSecond) {
|
||||
sliderPositionSeconds.value = newSecond;
|
||||
}
|
||||
}
|
||||
|
||||
void updatePositionSecond() {
|
||||
int newSecond = position.value.inSeconds;
|
||||
int newSecond = position.inSeconds;
|
||||
if (positionSeconds.value != newSecond) {
|
||||
positionSeconds.value = newSecond;
|
||||
}
|
||||
}
|
||||
|
||||
void updateDurationSecond() {
|
||||
if (durationSeconds.value != duration.value) {
|
||||
durationSeconds.value = duration.value;
|
||||
}
|
||||
}
|
||||
|
||||
void updateBufferedSecond() {
|
||||
int newSecond = buffered.value.inSeconds;
|
||||
if (bufferedSeconds.value != newSecond) {
|
||||
@@ -653,9 +642,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
);
|
||||
// 获取视频时长 00:00
|
||||
this.duration.value = duration ?? _videoPlayerController!.state.duration;
|
||||
position.value = buffered.value = sliderPosition.value =
|
||||
seekTo ?? Duration.zero;
|
||||
updateDurationSecond();
|
||||
position = buffered.value = sliderPosition = seekTo ?? Duration.zero;
|
||||
updatePositionSecond();
|
||||
updateSliderPositionSecond();
|
||||
updateBufferedSecond();
|
||||
@@ -766,7 +753,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
isBuffering.value = false;
|
||||
buffered.value = Duration.zero;
|
||||
_heartDuration = 0;
|
||||
position.value = Duration.zero;
|
||||
position = Duration.zero;
|
||||
// 初始化时清空弹幕,防止上次重叠
|
||||
danmakuController?.clear();
|
||||
|
||||
@@ -817,6 +804,8 @@ class PlPlayerController with BlockConfigMixin {
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, String> extras = {};
|
||||
|
||||
// 音轨
|
||||
final String audioUri;
|
||||
if (isFileSource) {
|
||||
@@ -825,12 +814,12 @@ class PlPlayerController with BlockConfigMixin {
|
||||
: path.join(dirPath!, typeTag!, PathUtils.audioNameType2);
|
||||
} else if (dataSource.audioSource?.isNotEmpty == true) {
|
||||
audioUri = Platform.isWindows
|
||||
? dataSource.audioSource!.replaceAll(';', '\\;')
|
||||
: dataSource.audioSource!.replaceAll(':', '\\:');
|
||||
? dataSource.audioSource!.replaceAll(';', r'\;')
|
||||
: dataSource.audioSource!.replaceAll(':', r'\:');
|
||||
} else {
|
||||
audioUri = '';
|
||||
}
|
||||
await pp.setProperty('audio-files', audioUri);
|
||||
if (audioUri.isNotEmpty) extras['audio-files'] = '"$audioUri"';
|
||||
|
||||
_videoController ??= VideoController(
|
||||
player,
|
||||
@@ -843,8 +832,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
|
||||
player.setPlaylistMode(looping);
|
||||
|
||||
final Map<String, String>? filters;
|
||||
if (Platform.isAndroid) {
|
||||
if (kDebugMode || Platform.isAndroid) {
|
||||
String audioNormalization = AudioNormalization.getParamFromConfig(
|
||||
Pref.audioNormalization,
|
||||
);
|
||||
@@ -867,11 +855,9 @@ class PlPlayerController with BlockConfigMixin {
|
||||
AudioNormalization.getParamFromConfig(Pref.fallbackNormalization),
|
||||
);
|
||||
}
|
||||
filters = audioNormalization.isEmpty
|
||||
? null
|
||||
: {'lavfi-complex': '"[aid1] $audioNormalization [ao]"'};
|
||||
} else {
|
||||
filters = null;
|
||||
if (audioNormalization.isNotEmpty) {
|
||||
extras['lavfi-complex'] = '"[aid1] $audioNormalization [ao]"';
|
||||
}
|
||||
}
|
||||
|
||||
// if (kDebugMode) debugPrint(filters.toString());
|
||||
@@ -895,7 +881,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
videoUri,
|
||||
httpHeaders: dataSource.httpHeaders,
|
||||
start: seekTo,
|
||||
extras: filters,
|
||||
extras: extras.isEmpty ? null : extras,
|
||||
),
|
||||
play: false,
|
||||
);
|
||||
@@ -915,23 +901,22 @@ class PlPlayerController with BlockConfigMixin {
|
||||
SmartDialog.showToast('视频源为空,请重新进入本页面');
|
||||
return false;
|
||||
}
|
||||
String? audioUri;
|
||||
if (!isLive) {
|
||||
if (dataSource.audioSource.isNullOrEmpty) {
|
||||
SmartDialog.showToast('音频源为空');
|
||||
} else {
|
||||
await (_videoPlayerController!.platform!).setProperty(
|
||||
'audio-files',
|
||||
Platform.isWindows
|
||||
? dataSource.audioSource!.replaceAll(';', '\\;')
|
||||
: dataSource.audioSource!.replaceAll(':', '\\:'),
|
||||
);
|
||||
audioUri = Platform.isWindows
|
||||
? dataSource.audioSource!.replaceAll(';', '\\;')
|
||||
: dataSource.audioSource!.replaceAll(':', '\\:');
|
||||
}
|
||||
}
|
||||
await _videoPlayerController!.open(
|
||||
Media(
|
||||
dataSource.videoSource!,
|
||||
httpHeaders: dataSource.httpHeaders,
|
||||
start: position.value,
|
||||
start: position,
|
||||
extras: audioUri == null ? null : {'audio-files': '"$audioUri"'},
|
||||
),
|
||||
play: true,
|
||||
);
|
||||
@@ -1038,10 +1023,10 @@ class PlPlayerController with BlockConfigMixin {
|
||||
makeHeartBeat(positionSeconds.value, type: HeartBeatType.completed);
|
||||
}),
|
||||
controllerStream.position.listen((event) {
|
||||
position.value = event;
|
||||
position = event;
|
||||
updatePositionSecond();
|
||||
if (!isSliderMoving.value) {
|
||||
sliderPosition.value = event;
|
||||
sliderPosition = event;
|
||||
updateSliderPositionSecond();
|
||||
}
|
||||
|
||||
@@ -1069,7 +1054,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
if (kDebugMode)
|
||||
controllerStream.log.listen(((PlayerLog log) {
|
||||
if (log.level == 'error' || log.level == 'fatal') {
|
||||
Utils.reportError('${log.prefix}: ${log.text}', null);
|
||||
Utils.reportError('${log.level}: ${log.prefix}: ${log.text}', null);
|
||||
} else {
|
||||
debugPrint(log.toString());
|
||||
}
|
||||
@@ -1140,12 +1125,8 @@ class PlPlayerController with BlockConfigMixin {
|
||||
isLive,
|
||||
);
|
||||
}),
|
||||
position.listen((Duration event) {
|
||||
EasyThrottle.throttle(
|
||||
'mediaServicePosition',
|
||||
const Duration(seconds: 1),
|
||||
() => videoPlayerServiceHandler!.onPositionChange(event),
|
||||
);
|
||||
positionSeconds.listen((int event) {
|
||||
videoPlayerServiceHandler!.onPositionChange(Duration(seconds: event));
|
||||
}),
|
||||
],
|
||||
};
|
||||
@@ -1167,7 +1148,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
if (position < Duration.zero) {
|
||||
position = Duration.zero;
|
||||
}
|
||||
this.position.value = position;
|
||||
this.position = position;
|
||||
updatePositionSecond();
|
||||
_heartDuration = position.inSeconds;
|
||||
if (duration.value.inSeconds != 0) {
|
||||
@@ -1194,7 +1175,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
if (_playerCount == 0) {
|
||||
_timerForSeek?.cancel();
|
||||
_timerForSeek = null;
|
||||
} else if (duration.value.inSeconds != 0) {
|
||||
} else if (duration.value != Duration.zero) {
|
||||
try {
|
||||
await _videoPlayerController?.stream.buffer.first;
|
||||
danmakuController?.clear();
|
||||
@@ -1288,8 +1269,8 @@ class PlPlayerController with BlockConfigMixin {
|
||||
}
|
||||
|
||||
/// 调整播放时间
|
||||
void onChangedSlider(double v) {
|
||||
sliderPosition.value = Duration(seconds: v.floor());
|
||||
void onChangedSlider(int v) {
|
||||
sliderPosition = Duration(seconds: v);
|
||||
updateSliderPositionSecond();
|
||||
}
|
||||
|
||||
@@ -1305,7 +1286,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
|
||||
void onUpdatedSliderProgress(Duration value) {
|
||||
sliderTempPosition.value = value;
|
||||
sliderPosition.value = value;
|
||||
sliderPosition = value;
|
||||
updateSliderPositionSecond();
|
||||
}
|
||||
|
||||
@@ -1350,14 +1331,6 @@ class PlPlayerController with BlockConfigMixin {
|
||||
});
|
||||
}
|
||||
|
||||
void volumeUpdated() {
|
||||
showVolumeStatus.value = true;
|
||||
_timerForShowingVolume?.cancel();
|
||||
_timerForShowingVolume = Timer(const Duration(seconds: 1), () {
|
||||
showVolumeStatus.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
/// Toggle Change the videofit accordingly
|
||||
void toggleVideoFit(VideoFitType value) {
|
||||
videoFit.value = value;
|
||||
@@ -1440,7 +1413,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
|
||||
bool get _isCompleted =>
|
||||
videoPlayerController!.state.completed ||
|
||||
(duration.value - position.value).inMilliseconds <= 50;
|
||||
(duration.value - position).inMilliseconds <= 50;
|
||||
|
||||
// 双击播放、暂停
|
||||
Future<void> onDoubleTapCenter() async {
|
||||
@@ -1464,11 +1437,11 @@ class PlPlayerController with BlockConfigMixin {
|
||||
}
|
||||
|
||||
void onForward(Duration duration) {
|
||||
onForwardBackward(position.value + duration);
|
||||
onForwardBackward(position + duration);
|
||||
}
|
||||
|
||||
void onBackward(Duration duration) {
|
||||
onForwardBackward(position.value - duration);
|
||||
onForwardBackward(position - duration);
|
||||
}
|
||||
|
||||
void onForwardBackward(Duration duration) {
|
||||
@@ -1604,7 +1577,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
}
|
||||
|
||||
// 记录播放记录
|
||||
Future<void> makeHeartBeat(
|
||||
Future<void>? makeHeartBeat(
|
||||
int progress, {
|
||||
HeartBeatType type = HeartBeatType.playing,
|
||||
bool isManual = false,
|
||||
@@ -1615,41 +1588,26 @@ class PlPlayerController with BlockConfigMixin {
|
||||
dynamic seasonId,
|
||||
dynamic pgcType,
|
||||
VideoType? videoType,
|
||||
}) async {
|
||||
}) {
|
||||
if (isLive) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
if (!enableHeart || MineController.anonymity.value || progress == 0) {
|
||||
return;
|
||||
return null;
|
||||
} else if (playerStatus.isPaused) {
|
||||
if (!isManual) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
bool isComplete =
|
||||
playerStatus.isCompleted || type == HeartBeatType.completed;
|
||||
if ((durationSeconds.value - position.value).inMilliseconds > 1000) {
|
||||
if ((duration.value - position).inMilliseconds > 1000) {
|
||||
isComplete = false;
|
||||
}
|
||||
// 播放状态变化时,更新
|
||||
|
||||
if (type == HeartBeatType.status || type == HeartBeatType.completed) {
|
||||
await VideoHttp.heartBeat(
|
||||
aid: aid ?? _aid,
|
||||
bvid: bvid ?? _bvid,
|
||||
cid: cid ?? this.cid,
|
||||
progress: isComplete ? -1 : progress,
|
||||
epid: epid ?? _epid,
|
||||
seasonId: seasonId ?? _seasonId,
|
||||
subType: pgcType ?? _pgcType,
|
||||
videoType: videoType ?? _videoType,
|
||||
);
|
||||
return;
|
||||
}
|
||||
// 正常播放时,间隔5秒更新一次
|
||||
else if (progress - _heartDuration >= 5) {
|
||||
_heartDuration = progress;
|
||||
await VideoHttp.heartBeat(
|
||||
Future<void> send() {
|
||||
return VideoHttp.heartBeat(
|
||||
aid: aid ?? _aid,
|
||||
bvid: bvid ?? _bvid,
|
||||
cid: cid ?? this.cid,
|
||||
@@ -1660,6 +1618,23 @@ class PlPlayerController with BlockConfigMixin {
|
||||
videoType: videoType ?? _videoType,
|
||||
);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case HeartBeatType.playing:
|
||||
if (progress - _heartDuration >= 5) {
|
||||
_heartDuration = progress;
|
||||
return send();
|
||||
}
|
||||
case HeartBeatType.status:
|
||||
if (progress - _heartDuration >= 2) {
|
||||
_heartDuration = progress;
|
||||
return send();
|
||||
}
|
||||
case HeartBeatType.completed:
|
||||
if (isComplete) progress = -1;
|
||||
return send();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void setPlayRepeat(PlayRepeat type) {
|
||||
@@ -1705,7 +1680,6 @@ class PlPlayerController with BlockConfigMixin {
|
||||
Utils.channel.setMethodCallHandler(null);
|
||||
_timer?.cancel();
|
||||
_timerForSeek?.cancel();
|
||||
_timerForShowingVolume?.cancel();
|
||||
// _position.close();
|
||||
// _playerEventSubs?.cancel();
|
||||
// _sliderPosition.close();
|
||||
@@ -1775,9 +1749,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
return;
|
||||
}
|
||||
if (videoShot case Success(:final response)) {
|
||||
if (!showPreview.value) {
|
||||
showPreview.value = true;
|
||||
}
|
||||
showPreview.value = true;
|
||||
previewIndex.value = max(
|
||||
0,
|
||||
(response.index.where((item) => item <= seconds).length - 2),
|
||||
|
||||
Reference in New Issue
Block a user