diff --git a/lib/src/providers/api/media_received.dart b/lib/src/providers/api/media_received.dart index 05a16d9..da47fca 100644 --- a/lib/src/providers/api/media_received.dart +++ b/lib/src/providers/api/media_received.dart @@ -181,7 +181,7 @@ Future handleDownloadData(DownloadData data) async { await writeMediaFile(media.messageId, "mp4", splited[1]); } - await writeMediaFile(media.messageId, "image", imageBytes); + await writeMediaFile(media.messageId, "png", imageBytes); } catch (e) { Logger("media_received.dart").info("Decryption error: $e"); await twonlyDatabase.messagesDao.updateMessageByMessageId( @@ -207,7 +207,7 @@ Future handleDownloadData(DownloadData data) async { } Future getImageBytes(int mediaId) async { - return await readMediaFile(mediaId, "image"); + return await readMediaFile(mediaId, "png"); } Future getVideoPath(int mediaId) async { diff --git a/lib/src/providers/api/media_send.dart b/lib/src/providers/api/media_send.dart index f3f30f3..0809f4a 100644 --- a/lib/src/providers/api/media_send.dart +++ b/lib/src/providers/api/media_send.dart @@ -17,6 +17,7 @@ import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/notification_service.dart'; +import 'package:video_compress/video_compress.dart'; Future sendMediaFile( List userIds, @@ -43,9 +44,9 @@ Future sendMediaFile( if (mediaUploadId != null) { if (videoFilePath != null) { String basePath = await getMediaFilePath(mediaUploadId, "send"); - await File(videoFilePath.path).rename("$basePath.video"); + await File(videoFilePath.path).rename("$basePath.mp4"); } - await writeMediaFile(mediaUploadId, "image", imageBytes); + await writeMediaFile(mediaUploadId, "png", imageBytes); await handleSingleMediaFile(mediaUploadId); } } @@ -165,7 +166,7 @@ Future handleAddToMessageDb(MediaUpload media) async { } Future handleCompressionState(MediaUpload media) async { - Uint8List imageBytes = await readMediaFile(media, "image"); + Uint8List imageBytes = await readMediaFile(media, "png"); try { Uint8List imageBytesCompressed = @@ -184,54 +185,56 @@ Future handleCompressionState(MediaUpload media) async { ); } await writeMediaFile( - media.mediaUploadId, "image.compressed", imageBytesCompressed); + media.mediaUploadId, "compressed.png", imageBytesCompressed); } catch (e) { Logger("media_send.dart").shout("$e"); // as a fall back use the original image - await writeMediaFile(media.mediaUploadId, "image.compressed", imageBytes); + await writeMediaFile(media.mediaUploadId, "compressed.png", imageBytes); } if (media.metadata.isVideo) { String basePath = await getMediaFilePath(media.mediaUploadId, "send"); - File videoOriginalFile = File("$basePath.video"); - File videoCompressedFile = File("$basePath.video.compressed"); + File videoOriginalFile = File("$basePath.mp4"); + File videoCompressedFile = File("$basePath.compressed.mp4"); - // MediaInfo? mediaInfo; + MediaInfo? mediaInfo; try { - // mediaInfo = await VideoCompress.compressVideo( - // videoOriginalFile.path, - // quality: VideoQuality.Res1280x720Quality, - // deleteOrigin: false, - // includeAudio: media.metadata.videoWithAudio, - // ); + mediaInfo = await VideoCompress.compressVideo( + videoOriginalFile.path, + quality: VideoQuality.Res1280x720Quality, + deleteOrigin: false, + includeAudio: + true, // https://github.com/jonataslaw/VideoCompress/issues/184 + ); - // if (mediaInfo!.filesize! >= 20 * 1000 * 1000) { - // // if the media file is over 20MB compress it with low quality - // mediaInfo = await VideoCompress.compressVideo( - // videoOriginalFile.path, - // quality: VideoQuality.Res960x540Quality, - // deleteOrigin: false, - // includeAudio: media.metadata.videoWithAudio, - // ); - // } + if (mediaInfo!.filesize! >= 20 * 1000 * 1000) { + // if the media file is over 20MB compress it with low quality + mediaInfo = await VideoCompress.compressVideo( + videoOriginalFile.path, + quality: VideoQuality.Res960x540Quality, + deleteOrigin: false, + includeAudio: media.metadata.videoWithAudio, + ); + } } catch (e) { Logger("media_send.dart").shout("Video compression: $e"); } - // if (mediaInfo == null) { - // as a fall back use the non compressed version - await videoOriginalFile.copy(videoCompressedFile.path); - await videoOriginalFile.delete(); - // } else { - // Logger("media_send.dart").shout("Error compressing video."); - // mediaInfo!.file!.rename(videoCompressedFile.path); - // } + if (mediaInfo == null) { + Logger("media_send.dart").shout("Error compressing video."); + // as a fall back use the non compressed version + await videoOriginalFile.copy(videoCompressedFile.path); + await videoOriginalFile.delete(); + } else { + await mediaInfo.file!.copy(videoCompressedFile.path); + await mediaInfo.file!.delete(); + } } // delete non compressed media files - await deleteMediaFile(media, "image"); - await deleteMediaFile(media, "video"); + await deleteMediaFile(media, "png"); + await deleteMediaFile(media, "mp4"); await twonlyDatabase.mediaUploadsDao.updateMediaUpload( media.mediaUploadId, @@ -246,10 +249,10 @@ Future handleCompressionState(MediaUpload media) async { Future handleEncryptionState(MediaUpload media) async { var state = MediaEncryptionData(); - Uint8List dataToEncrypt = await readMediaFile(media, "image.compressed"); + Uint8List dataToEncrypt = await readMediaFile(media, "compressed.png"); if (media.metadata.isVideo) { - Uint8List compressedVideo = await readMediaFile(media, "video.compressed"); + Uint8List compressedVideo = await readMediaFile(media, "compressed.mp4"); dataToEncrypt = combineUint8Lists(dataToEncrypt, compressedVideo); } diff --git a/lib/src/views/camera/camera_preview_view.dart b/lib/src/views/camera/camera_preview_view.dart index e7e897d..9a59307 100644 --- a/lib/src/views/camera/camera_preview_view.dart +++ b/lib/src/views/camera/camera_preview_view.dart @@ -41,6 +41,7 @@ class _CameraPreviewViewState extends State { bool useHighQuality = false; bool isVideoRecording = false; bool hasAudioPermission = true; + bool videoWithAudio = true; DateTime? videoRecordingStarted; Timer? videoRecordingTimer; DateTime currentTime = DateTime.now(); @@ -105,7 +106,7 @@ class _CameraPreviewViewState extends State { controller = CameraController( gCameras[sCameraId], ResolutionPreset.high, - enableAudio: await Permission.microphone.isGranted, + enableAudio: await Permission.microphone.isGranted && videoWithAudio, ); controller?.initialize().then((_) async { if (!mounted) { @@ -508,7 +509,23 @@ class _CameraPreviewViewState extends State { tooltipText: "Allow microphone access for video recording.", onPressed: requestMicrophonePermission, - ) + ), + if (hasAudioPermission) + ActionButton( + (videoWithAudio) + ? Icons.volume_up_rounded + : Icons.volume_off_rounded, + tooltipText: "Record video with audio.", + color: (videoWithAudio) + ? Colors.white + : Colors.white.withAlpha(160), + onPressed: () async { + setState(() { + videoWithAudio = !videoWithAudio; + }); + selectCamera(cameraId); + }, + ), ], ), ), diff --git a/lib/src/views/camera/share_image_editor_view.dart b/lib/src/views/camera/share_image_editor_view.dart index 33f2537..7da0beb 100644 --- a/lib/src/views/camera/share_image_editor_view.dart +++ b/lib/src/views/camera/share_image_editor_view.dart @@ -196,18 +196,19 @@ class _ShareImageEditorView extends State { }, ), ), - if (widget.videoFilePath != null) const SizedBox(height: 8), - if (widget.videoFilePath != null) - ActionButton( - (videoWithAudio) ? Icons.volume_up_rounded : Icons.volume_off_rounded, - tooltipText: context.lang.protectAsARealTwonly, - color: Colors.white, - onPressed: () async { - setState(() { - videoWithAudio = !videoWithAudio; - }); - }, - ), + // https://github.com/jonataslaw/VideoCompress/issues/184 + // if (widget.videoFilePath != null) const SizedBox(height: 8), + // if (widget.videoFilePath != null) + // ActionButton( + // (videoWithAudio) ? Icons.volume_up_rounded : Icons.volume_off_rounded, + // tooltipText: context.lang.protectAsARealTwonly, + // color: Colors.white, + // onPressed: () async { + // setState(() { + // videoWithAudio = !videoWithAudio; + // }); + // }, + // ), const SizedBox(height: 8), ActionButton( FontAwesomeIcons.shieldHeart, @@ -287,6 +288,7 @@ class _ShareImageEditorView extends State { isRealTwonly: _isRealTwonly, maxShowTime: maxShowTime, preselectedUser: widget.sendTo, + videoFilePath: widget.videoFilePath, ), ), ); diff --git a/lib/src/views/camera/share_image_view.dart b/lib/src/views/camera/share_image_view.dart index 924c770..7ed43ac 100644 --- a/lib/src/views/camera/share_image_view.dart +++ b/lib/src/views/camera/share_image_view.dart @@ -23,7 +23,7 @@ class ShareImageView extends StatefulWidget { required this.isRealTwonly, required this.maxShowTime, this.preselectedUser, - this.videoFilePath, + required this.videoFilePath, this.enableVideoAudio}); final Future imageBytesFuture; final bool isRealTwonly;