From d49515011d91d81fe7eec2823dfab000164d0df1 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 27 Dec 2021 13:01:51 +0100 Subject: [PATCH] feat: Enable compression and thumbnails for videos --- lib/pages/add_story/add_story.dart | 14 +++---- lib/pages/chat/send_file_dialog.dart | 3 ++ lib/utils/resize_image.dart | 50 +++++++++++++++++++++++++ lib/utils/room_send_file_extension.dart | 4 ++ pubspec.lock | 7 ++++ pubspec.yaml | 1 + 6 files changed, 72 insertions(+), 7 deletions(-) diff --git a/lib/pages/add_story/add_story.dart b/lib/pages/add_story/add_story.dart index c0537adc..ceb33fae 100644 --- a/lib/pages/add_story/add_story.dart +++ b/lib/pages/add_story/add_story.dart @@ -15,7 +15,8 @@ import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/pages/add_story/add_story_view.dart'; import 'package:fluffychat/pages/add_story/invite_story_page.dart'; -import 'package:fluffychat/utils/resize_image.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_file_extension.dart'; +import 'package:fluffychat/utils/room_send_file_extension.dart'; import 'package:fluffychat/utils/string_color.dart'; import 'package:fluffychat/widgets/matrix.dart'; import '../../utils/matrix_sdk_extensions.dart/client_stories_extension.dart'; @@ -123,17 +124,16 @@ class AddStoryController extends State { if (storiesRoom == null) throw ('Stories room is null'); final video = this.video; if (video != null) { - await storiesRoom.sendFileEvent( - video, + await storiesRoom.sendFileEventWithThumbnail( + video.detectFileType, extraContent: {'body': controller.text}, ); return; } - var image = this.image; + final image = this.image; if (image != null) { - image = await image.resizeImage(); - await storiesRoom.sendFileEvent( - image, + await storiesRoom.sendFileEventWithThumbnail( + image.detectFileType, extraContent: {'body': controller.text}, ); return; diff --git a/lib/pages/chat/send_file_dialog.dart b/lib/pages/chat/send_file_dialog.dart index 9d53f2f4..272210b3 100644 --- a/lib/pages/chat/send_file_dialog.dart +++ b/lib/pages/chat/send_file_dialog.dart @@ -38,6 +38,9 @@ class _SendFileDialogState extends State { file.bytes.length > minSizeToCompress) { file = await file.resizeImage(); } + if (file is MatrixVideoFile && file.bytes.length > minSizeToCompress) { + file = await file.resizeVideo(); + } await widget.room.sendFileEventWithThumbnail(file); } diff --git a/lib/utils/resize_image.dart b/lib/utils/resize_image.dart index 543884cb..359650b8 100644 --- a/lib/utils/resize_image.dart +++ b/lib/utils/resize_image.dart @@ -1,5 +1,6 @@ //@dart=2.12 +import 'dart:io'; import 'dart:math' as math; import 'dart:typed_data'; @@ -8,11 +9,60 @@ import 'package:flutter/foundation.dart'; import 'package:blurhash_dart/blurhash_dart.dart'; import 'package:image/image.dart'; import 'package:matrix/matrix.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:video_compress/video_compress.dart'; + +import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/utils/sentry_controller.dart'; extension ResizeImage on MatrixFile { static const int max = 1200; static const int quality = 40; + Future resizeVideo() async { + if (!PlatformInfos.isMobile) return this; + final tmpDir = await getTemporaryDirectory(); + final tmpFile = File(tmpDir.path + name); + if (await tmpFile.exists() == false) { + await tmpFile.writeAsBytes(bytes); + try { + final mediaInfo = await VideoCompress.compressVideo(tmpFile.path); + if (mediaInfo == null) return this; + return MatrixVideoFile( + bytes: await tmpFile.readAsBytes(), + name: name, + mimeType: mimeType, + width: mediaInfo.width, + height: mediaInfo.height, + duration: mediaInfo.duration?.round(), + ); + } catch (e, s) { + SentryController.captureException(e, s); + } + } + return this; + } + + Future getVideoThumbnail() async { + if (!PlatformInfos.isMobile) return null; + final tmpDir = await getTemporaryDirectory(); + final tmpFile = File(tmpDir.path + name); + if (await tmpFile.exists() == false) { + await tmpFile.writeAsBytes(bytes); + } + try { + final bytes = await VideoCompress.getByteThumbnail(tmpFile.path); + if (bytes == null) return null; + return MatrixImageFile( + bytes: bytes, + name: name, + ).resizeImage(); + } catch (e, s) { + SentryController.captureException(e, s); + } + return null; + } + Future resizeImage({ bool calcBlurhash = true, int max = ResizeImage.max, diff --git a/lib/utils/room_send_file_extension.dart b/lib/utils/room_send_file_extension.dart index 9ff94c8c..0b2775a7 100644 --- a/lib/utils/room_send_file_extension.dart +++ b/lib/utils/room_send_file_extension.dart @@ -11,6 +11,7 @@ extension RoomSendFileExtension on Room { Event? inReplyTo, String? editEventId, bool? waitUntilSent, + Map? extraContent, }) async { MatrixImageFile? thumbnail; if (file is MatrixImageFile) { @@ -19,6 +20,8 @@ extension RoomSendFileExtension on Room { if (thumbnail.size > file.size ~/ 2) { thumbnail = null; } + } else if (file is MatrixVideoFile) { + thumbnail = await file.getVideoThumbnail(); } return sendFileEvent( @@ -28,6 +31,7 @@ extension RoomSendFileExtension on Room { editEventId: editEventId, waitUntilSent: waitUntilSent ?? false, thumbnail: thumbnail, + extraContent: extraContent, ); } } diff --git a/pubspec.lock b/pubspec.lock index 120cdc9a..ab4d2a90 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1594,6 +1594,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + video_compress: + dependency: "direct main" + description: + name: video_compress + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" video_player: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 94cf3de8..96b6ad04 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -72,6 +72,7 @@ dependencies: unifiedpush: ^3.0.1 universal_html: ^2.0.8 url_launcher: ^6.0.12 + video_compress: ^3.1.0 video_player: ^2.2.10 vrouter: ^1.2.0+15 wakelock: ^0.5.6