mpv: screenshot, subtitle rendering

This commit is contained in:
Thibault Deckers 2023-07-16 00:46:21 +02:00
parent 25753e5274
commit 017264d2bc
9 changed files with 205 additions and 95 deletions

View file

@ -70,10 +70,12 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
}
Future<void> _captureFrame(BuildContext context, AvesEntry entry, AvesVideoController controller) async {
final positionMillis = controller.currentPosition;
final bytes = await controller.captureFrame();
final destinationAlbum = androidFileUtils.avesVideoCapturesPath;
final positionMillis = controller.currentPosition;
final Map<String, dynamic> newFields = {};
final bytes = await controller.captureFrame();
if (bytes != null) {
if (!await checkStoragePermissionForAlbums(context, {destinationAlbum})) return;
if (!await checkFreeSpace(context, bytes.length, destinationAlbum)) return;
@ -90,14 +92,15 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
}
};
final newFields = await mediaEditService.captureFrame(
newFields.addAll(await mediaEditService.captureFrame(
entry,
desiredName: '${entry.bestTitle}_${'$positionMillis'.padLeft(8, '0')}',
exif: exif,
bytes: bytes,
destinationAlbum: destinationAlbum,
nameConflictStrategy: NameConflictStrategy.rename,
);
));
}
final success = newFields.isNotEmpty;
final l10n = context.l10n;

View file

@ -134,10 +134,12 @@ class WallpaperButtons extends StatelessWidget with FeedbackMixin {
final videoController = context.read<VideoConductor>().getController(entry);
if (videoController != null) {
final bytes = await videoController.captureFrame();
if (bytes != null) {
needOrientation = rotationDegrees != 0 || isFlipped;
needCrop = true;
provider = MemoryImage(bytes);
}
}
} else if (entry.canDecode) {
if (entry.useTiles) {
// provider image is already cropped, but not rotated

View file

@ -120,7 +120,7 @@ abstract class AvesVideoController {
List<MediaStreamSummary> get streams;
Future<Uint8List> captureFrame();
Future<Uint8List?> captureFrame();
Future<void> mute(bool muted);

View file

@ -371,7 +371,7 @@ class IjkVideoController extends AvesVideoController {
Future<void> _applySpeed() => _instance.setSpeed(speed);
@override
Future<Uint8List> captureFrame() {
Future<Uint8List?> captureFrame() {
if (!_instance.value.videoRenderStart) {
return Future.error('cannot capture frame when video is not rendered');
}

View file

@ -25,7 +25,7 @@ class MpvVideoController extends AvesVideoController {
double get maxSpeed => 4;
@override
final ValueNotifier<bool> canCaptureFrameNotifier = ValueNotifier(false);
final ValueNotifier<bool> canCaptureFrameNotifier = ValueNotifier(true);
@override
final ValueNotifier<bool> canMuteNotifier = ValueNotifier(true);
@ -49,14 +49,13 @@ class MpvVideoController extends AvesVideoController {
_instance = Player(
configuration: const PlayerConfiguration(
libass: false,
logLevel: MPVLogLevel.warn,
),
);
_initController();
_init();
// TODO TLAD listening
// canCaptureFrameNotifier.value = captureFrameEnabled && started;
_startListening();
}
@ -185,7 +184,7 @@ class MpvVideoController extends AvesVideoController {
Stream<int> get positionStream => _instance.stream.position.map((pos) => pos.inMilliseconds);
@override
Stream<String?> get timedTextStream => _timedTextStreamController.stream;
Stream<String?> get timedTextStream => _instance.stream.subtitle.map((v) => v.isEmpty ? null : v[0]);
@override
bool get isMuted => _instance.state.volume == 0;
@ -200,10 +199,7 @@ class MpvVideoController extends AvesVideoController {
set speed(double speed) => _instance.setRate(speed);
@override
Future<Uint8List> captureFrame() {
// TODO: implement captureFrame
throw UnimplementedError();
}
Future<Uint8List?> captureFrame() => _instance.screenshot();
@override
Widget buildPlayerWidget(BuildContext context) {
@ -214,6 +210,9 @@ class MpvVideoController extends AvesVideoController {
alignment: Alignment.center,
controls: NoVideoControls,
wakelock: false,
subtitleViewConfiguration: const SubtitleViewConfiguration(
style: TextStyle(color: Colors.transparent),
),
);
}

View file

@ -1,6 +1,22 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
url: "https://pub.dev"
source: hosted
version: "3.3.7"
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
@ -46,6 +62,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.17.1"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
dbus:
dependency: transitive
description:
name: dbus
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
url: "https://pub.dev"
source: hosted
version: "0.7.8"
equatable:
dependency: transitive
description:
@ -96,6 +136,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
url: "https://pub.dev"
source: hosted
version: "4.0.17"
js:
dependency: transitive
description:
@ -123,34 +171,38 @@ packages:
media_kit:
dependency: "direct main"
description:
name: media_kit
sha256: "8c7d9417bed724a3fcaadd91c722fea042737cafb153aa1f1e6461a0fee683a3"
url: "https://pub.dev"
source: hosted
path: media_kit
ref: main
resolved-ref: "6d0f0401b8d87596a6167fd629912cff92003edc"
url: "https://github.com/alexmercerind/media_kit"
source: git
version: "1.0.2"
media_kit_libs_android_video:
dependency: "direct main"
description:
name: media_kit_libs_android_video
sha256: "228c3b182831e194bb178d4d22a1839af812c917cb76fe87d6fdc9ea4328dc81"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
path: media_kit_libs_android_video
ref: main
resolved-ref: "6d0f0401b8d87596a6167fd629912cff92003edc"
url: "https://github.com/alexmercerind/media_kit"
source: git
version: "1.2.0"
media_kit_native_event_loop:
dependency: "direct main"
description:
name: media_kit_native_event_loop
sha256: "5351f0c28124b5358756515d8619abad182cdefe967468d7fb5b274737cc2f59"
url: "https://pub.dev"
source: hosted
path: media_kit_native_event_loop
ref: main
resolved-ref: "6d0f0401b8d87596a6167fd629912cff92003edc"
url: "https://github.com/alexmercerind/media_kit"
source: git
version: "1.0.6"
media_kit_video:
dependency: "direct main"
description:
name: media_kit_video
sha256: d31a0eab80cafadccdedb663d8a127750e38b8c75c1aa83d8943f8119b88cf99
url: "https://pub.dev"
source: hosted
path: media_kit_video
ref: main
resolved-ref: "6d0f0401b8d87596a6167fd629912cff92003edc"
url: "https://github.com/alexmercerind/media_kit"
source: git
version: "1.0.2"
meta:
dependency: transitive
@ -160,6 +212,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
package_info_plus:
dependency: transitive
description:
name: package_info_plus
sha256: ceb027f6bc6a60674a233b4a90a7658af1aebdea833da0b5b53c1e9821a78c7b
url: "https://pub.dev"
source: hosted
version: "4.0.2"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
path:
dependency: transitive
description:
@ -168,6 +236,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.3"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
url: "https://pub.dev"
source: hosted
version: "5.4.0"
plugin_platform_interface:
dependency: transitive
description:
@ -176,6 +252,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
pointycastle:
dependency: transitive
description:
name: pointycastle
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
safe_local_storage:
dependency: transitive
description:
@ -309,54 +393,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.7"
wakelock:
wakelock_plus:
dependency: transitive
description:
name: wakelock
sha256: "769ecf42eb2d07128407b50cb93d7c10bd2ee48f0276ef0119db1d25cc2f87db"
name: wakelock_plus
sha256: aac3f3258f01781ec9212df94eecef1eb9ba9350e106728def405baa096ba413
url: "https://pub.dev"
source: hosted
version: "0.6.2"
wakelock_macos:
version: "1.1.1"
wakelock_plus_platform_interface:
dependency: transitive
description:
name: wakelock_macos
sha256: "047c6be2f88cb6b76d02553bca5a3a3b95323b15d30867eca53a19a0a319d4cd"
name: wakelock_plus_platform_interface
sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
wakelock_platform_interface:
dependency: transitive
description:
name: wakelock_platform_interface
sha256: "1f4aeb81fb592b863da83d2d0f7b8196067451e4df91046c26b54a403f9de621"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
wakelock_web:
dependency: transitive
description:
name: wakelock_web
sha256: "1b256b811ee3f0834888efddfe03da8d18d0819317f20f6193e2922b41a501b5"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
wakelock_windows:
dependency: transitive
description:
name: wakelock_windows
sha256: "857f77b3fe6ae82dd045455baa626bc4b93cb9bb6c86bf3f27c182167c3a5567"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
version: "1.1.0"
win32:
dependency: transitive
description:
name: win32
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee
url: "https://pub.dev"
source: hosted
version: "3.1.4"
version: "5.0.5"
xml:
dependency: transitive
description:
name: xml
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
url: "https://pub.dev"
source: hosted
version: "6.3.0"
sdks:
dart: ">=3.0.0 <4.0.0"
flutter: ">=3.7.0"
flutter: ">=3.3.0"

View file

@ -23,7 +23,7 @@ dependencies:
dev_dependencies:
flutter_lints:
#dependency_overrides:
dependency_overrides:
# media_kit:
# path: ../../../media_kit/media_kit
# media_kit_video:
@ -32,5 +32,26 @@ dev_dependencies:
# path: ../../../media_kit/media_kit_native_event_loop
# media_kit_libs_android_video:
# path: ../../../media_kit/media_kit_libs_android_video
media_kit:
git:
url: https://github.com/alexmercerind/media_kit
ref: main
path: media_kit
media_kit_video:
git:
url: https://github.com/alexmercerind/media_kit
ref: main
path: media_kit_video
media_kit_native_event_loop:
git:
url: https://github.com/alexmercerind/media_kit
ref: main
path: media_kit_native_event_loop
media_kit_libs_android_video:
git:
url: https://github.com/alexmercerind/media_kit
ref: main
path: media_kit_libs_android_video
flutter:

View file

@ -1569,7 +1569,7 @@ packages:
source: hosted
version: "1.2.0"
win32:
dependency: "direct overridden"
dependency: transitive
description:
name: win32
sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee

View file

@ -124,10 +124,7 @@ dev_dependencies:
shared_preferences_platform_interface:
test:
dependency_overrides:
# `media_kit v1.0.0` depends on `wakelock: ^0.6.2`
# which is incompatible with packages that moved on with Dart 3
win32: ^5.0.0
#dependency_overrides:
# media_kit:
# path: ../media_kit/media_kit
# media_kit_video:
@ -136,6 +133,26 @@ dependency_overrides:
# path: ../media_kit/media_kit_native_event_loop
# media_kit_libs_android_video:
# path: ../media_kit/media_kit_libs_android_video
# media_kit:
# git:
# url: https://github.com/alexmercerind/media_kit
# ref: main
# path: media_kit
# media_kit_video:
# git:
# url: https://github.com/alexmercerind/media_kit
# ref: main
# path: media_kit_video
# media_kit_native_event_loop:
# git:
# url: https://github.com/alexmercerind/media_kit
# ref: main
# path: media_kit_native_event_loop
# media_kit_libs_android_video:
# git:
# url: https://github.com/alexmercerind/media_kit
# ref: main
# path: media_kit_libs_android_video
flutter:
assets: