From 3d0a3ee2264430720329aefd1e10ac27f57c258f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Sat, 21 Jun 2025 10:05:14 +0200 Subject: [PATCH] fix: Workaround for reversed width and height of compressed videos sent from Android --- lib/pages/chat/events/video_player.dart | 13 +++++++++---- lib/pages/chat/send_file_dialog.dart | 18 ++++++++++++------ lib/utils/resize_video.dart | 15 ++++++++++----- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index 856bda50c..6b31eb774 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:flutter_linkify/flutter_linkify.dart'; @@ -36,11 +38,14 @@ class EventVideoPlayer extends StatelessWidget { .tryGet('xyz.amorgan.blurhash') ?? fallbackBlurHash; final fileDescription = event.fileDescription; + const maxDimension = 300.0; final infoMap = event.content.tryGetMap('info'); - final videoWidth = infoMap?.tryGet('w') ?? 400; - final videoHeight = infoMap?.tryGet('h') ?? 300; - const height = 300.0; - final width = videoWidth * (height / videoHeight); + final videoWidth = infoMap?.tryGet('w') ?? maxDimension; + final videoHeight = infoMap?.tryGet('h') ?? maxDimension; + + final modifier = max(videoWidth, videoHeight) / maxDimension; + final width = videoWidth / modifier; + final height = videoHeight / modifier; final durationInt = infoMap?.tryGet('duration'); final duration = diff --git a/lib/pages/chat/send_file_dialog.dart b/lib/pages/chat/send_file_dialog.dart index c786b6769..7b215496e 100644 --- a/lib/pages/chat/send_file_dialog.dart +++ b/lib/pages/chat/send_file_dialog.dart @@ -59,16 +59,22 @@ class SendFileDialogState extends State { final length = await xfile.length(); final mimeType = xfile.mimeType ?? lookupMimeType(xfile.path); - // If file is a video, shrink it! + // Generate video thumbnail if (PlatformInfos.isMobile && mimeType != null && - mimeType.startsWith('video') && - length > minSizeToCompress && - compress) { - scaffoldMessenger.showLoadingSnackBar(l10n.compressVideo); - file = await xfile.resizeVideo(); + mimeType.startsWith('video')) { scaffoldMessenger.showLoadingSnackBar(l10n.generatingVideoThumbnail); thumbnail = await xfile.getVideoThumbnail(); + } + + // If file is a video, shrink it! + if (PlatformInfos.isMobile && + mimeType != null && + mimeType.startsWith('video')) { + scaffoldMessenger.showLoadingSnackBar(l10n.compressVideo); + file = await xfile.getVideoInfo( + compress: length > minSizeToCompress && compress, + ); } else { if (length > maxUploadSize) { throw FileTooBigMatrixException(length, maxUploadSize); diff --git a/lib/utils/resize_video.dart b/lib/utils/resize_video.dart index 768677106..99a4c6b0a 100644 --- a/lib/utils/resize_video.dart +++ b/lib/utils/resize_video.dart @@ -8,22 +8,27 @@ extension ResizeImage on XFile { static const int max = 1200; static const int quality = 40; - Future resizeVideo() async { + Future getVideoInfo({bool compress = true}) async { MediaInfo? mediaInfo; try { if (PlatformInfos.isMobile) { // will throw an error e.g. on Android SDK < 18 - mediaInfo = await VideoCompress.compressVideo(path); + mediaInfo = compress + ? await VideoCompress.compressVideo(path, deleteOrigin: true) + : await VideoCompress.getMediaInfo(path); } } catch (e, s) { - Logs().w('Error while compressing video', e, s); + Logs().w('Error while fetching video media info', e, s); } + return MatrixVideoFile( bytes: (await mediaInfo?.file?.readAsBytes()) ?? await readAsBytes(), name: name, mimeType: mimeType, - width: mediaInfo?.width, - height: mediaInfo?.height, + // on Android width and height is reversed: + // https://github.com/jonataslaw/VideoCompress/issues/172 + width: PlatformInfos.isAndroid ? mediaInfo?.height : mediaInfo?.width, + height: PlatformInfos.isAndroid ? mediaInfo?.width : mediaInfo?.height, duration: mediaInfo?.duration?.round(), ); }