mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
fix video compression issues #25
This commit is contained in:
parent
0f7b1755ba
commit
06715e8ac9
5 changed files with 74 additions and 52 deletions
|
|
@ -181,7 +181,7 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
||||||
await writeMediaFile(media.messageId, "mp4", splited[1]);
|
await writeMediaFile(media.messageId, "mp4", splited[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await writeMediaFile(media.messageId, "image", imageBytes);
|
await writeMediaFile(media.messageId, "png", imageBytes);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("media_received.dart").info("Decryption error: $e");
|
Logger("media_received.dart").info("Decryption error: $e");
|
||||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||||
|
|
@ -207,7 +207,7 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List?> getImageBytes(int mediaId) async {
|
Future<Uint8List?> getImageBytes(int mediaId) async {
|
||||||
return await readMediaFile(mediaId, "image");
|
return await readMediaFile(mediaId, "png");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> getVideoPath(int mediaId) async {
|
Future<File?> getVideoPath(int mediaId) async {
|
||||||
|
|
|
||||||
|
|
@ -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.dart';
|
||||||
import 'package:twonly/src/providers/api/api_utils.dart';
|
import 'package:twonly/src/providers/api/api_utils.dart';
|
||||||
import 'package:twonly/src/services/notification_service.dart';
|
import 'package:twonly/src/services/notification_service.dart';
|
||||||
|
import 'package:video_compress/video_compress.dart';
|
||||||
|
|
||||||
Future sendMediaFile(
|
Future sendMediaFile(
|
||||||
List<int> userIds,
|
List<int> userIds,
|
||||||
|
|
@ -43,9 +44,9 @@ Future sendMediaFile(
|
||||||
if (mediaUploadId != null) {
|
if (mediaUploadId != null) {
|
||||||
if (videoFilePath != null) {
|
if (videoFilePath != null) {
|
||||||
String basePath = await getMediaFilePath(mediaUploadId, "send");
|
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);
|
await handleSingleMediaFile(mediaUploadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +166,7 @@ Future handleAddToMessageDb(MediaUpload media) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future handleCompressionState(MediaUpload media) async {
|
Future handleCompressionState(MediaUpload media) async {
|
||||||
Uint8List imageBytes = await readMediaFile(media, "image");
|
Uint8List imageBytes = await readMediaFile(media, "png");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Uint8List imageBytesCompressed =
|
Uint8List imageBytesCompressed =
|
||||||
|
|
@ -184,54 +185,56 @@ Future handleCompressionState(MediaUpload media) async {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await writeMediaFile(
|
await writeMediaFile(
|
||||||
media.mediaUploadId, "image.compressed", imageBytesCompressed);
|
media.mediaUploadId, "compressed.png", imageBytesCompressed);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("media_send.dart").shout("$e");
|
Logger("media_send.dart").shout("$e");
|
||||||
// as a fall back use the original image
|
// 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) {
|
if (media.metadata.isVideo) {
|
||||||
String basePath = await getMediaFilePath(media.mediaUploadId, "send");
|
String basePath = await getMediaFilePath(media.mediaUploadId, "send");
|
||||||
File videoOriginalFile = File("$basePath.video");
|
File videoOriginalFile = File("$basePath.mp4");
|
||||||
File videoCompressedFile = File("$basePath.video.compressed");
|
File videoCompressedFile = File("$basePath.compressed.mp4");
|
||||||
|
|
||||||
// MediaInfo? mediaInfo;
|
MediaInfo? mediaInfo;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// mediaInfo = await VideoCompress.compressVideo(
|
mediaInfo = await VideoCompress.compressVideo(
|
||||||
// videoOriginalFile.path,
|
videoOriginalFile.path,
|
||||||
// quality: VideoQuality.Res1280x720Quality,
|
quality: VideoQuality.Res1280x720Quality,
|
||||||
// deleteOrigin: false,
|
deleteOrigin: false,
|
||||||
// includeAudio: media.metadata.videoWithAudio,
|
includeAudio:
|
||||||
// );
|
true, // https://github.com/jonataslaw/VideoCompress/issues/184
|
||||||
|
);
|
||||||
|
|
||||||
// if (mediaInfo!.filesize! >= 20 * 1000 * 1000) {
|
if (mediaInfo!.filesize! >= 20 * 1000 * 1000) {
|
||||||
// // if the media file is over 20MB compress it with low quality
|
// if the media file is over 20MB compress it with low quality
|
||||||
// mediaInfo = await VideoCompress.compressVideo(
|
mediaInfo = await VideoCompress.compressVideo(
|
||||||
// videoOriginalFile.path,
|
videoOriginalFile.path,
|
||||||
// quality: VideoQuality.Res960x540Quality,
|
quality: VideoQuality.Res960x540Quality,
|
||||||
// deleteOrigin: false,
|
deleteOrigin: false,
|
||||||
// includeAudio: media.metadata.videoWithAudio,
|
includeAudio: media.metadata.videoWithAudio,
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("media_send.dart").shout("Video compression: $e");
|
Logger("media_send.dart").shout("Video compression: $e");
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (mediaInfo == null) {
|
if (mediaInfo == null) {
|
||||||
|
Logger("media_send.dart").shout("Error compressing video.");
|
||||||
// as a fall back use the non compressed version
|
// as a fall back use the non compressed version
|
||||||
await videoOriginalFile.copy(videoCompressedFile.path);
|
await videoOriginalFile.copy(videoCompressedFile.path);
|
||||||
await videoOriginalFile.delete();
|
await videoOriginalFile.delete();
|
||||||
// } else {
|
} else {
|
||||||
// Logger("media_send.dart").shout("Error compressing video.");
|
await mediaInfo.file!.copy(videoCompressedFile.path);
|
||||||
// mediaInfo!.file!.rename(videoCompressedFile.path);
|
await mediaInfo.file!.delete();
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete non compressed media files
|
// delete non compressed media files
|
||||||
await deleteMediaFile(media, "image");
|
await deleteMediaFile(media, "png");
|
||||||
await deleteMediaFile(media, "video");
|
await deleteMediaFile(media, "mp4");
|
||||||
|
|
||||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||||
media.mediaUploadId,
|
media.mediaUploadId,
|
||||||
|
|
@ -246,10 +249,10 @@ Future handleCompressionState(MediaUpload media) async {
|
||||||
Future handleEncryptionState(MediaUpload media) async {
|
Future handleEncryptionState(MediaUpload media) async {
|
||||||
var state = MediaEncryptionData();
|
var state = MediaEncryptionData();
|
||||||
|
|
||||||
Uint8List dataToEncrypt = await readMediaFile(media, "image.compressed");
|
Uint8List dataToEncrypt = await readMediaFile(media, "compressed.png");
|
||||||
|
|
||||||
if (media.metadata.isVideo) {
|
if (media.metadata.isVideo) {
|
||||||
Uint8List compressedVideo = await readMediaFile(media, "video.compressed");
|
Uint8List compressedVideo = await readMediaFile(media, "compressed.mp4");
|
||||||
dataToEncrypt = combineUint8Lists(dataToEncrypt, compressedVideo);
|
dataToEncrypt = combineUint8Lists(dataToEncrypt, compressedVideo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
bool useHighQuality = false;
|
bool useHighQuality = false;
|
||||||
bool isVideoRecording = false;
|
bool isVideoRecording = false;
|
||||||
bool hasAudioPermission = true;
|
bool hasAudioPermission = true;
|
||||||
|
bool videoWithAudio = true;
|
||||||
DateTime? videoRecordingStarted;
|
DateTime? videoRecordingStarted;
|
||||||
Timer? videoRecordingTimer;
|
Timer? videoRecordingTimer;
|
||||||
DateTime currentTime = DateTime.now();
|
DateTime currentTime = DateTime.now();
|
||||||
|
|
@ -105,7 +106,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
controller = CameraController(
|
controller = CameraController(
|
||||||
gCameras[sCameraId],
|
gCameras[sCameraId],
|
||||||
ResolutionPreset.high,
|
ResolutionPreset.high,
|
||||||
enableAudio: await Permission.microphone.isGranted,
|
enableAudio: await Permission.microphone.isGranted && videoWithAudio,
|
||||||
);
|
);
|
||||||
controller?.initialize().then((_) async {
|
controller?.initialize().then((_) async {
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
|
|
@ -508,7 +509,23 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
tooltipText:
|
tooltipText:
|
||||||
"Allow microphone access for video recording.",
|
"Allow microphone access for video recording.",
|
||||||
onPressed: requestMicrophonePermission,
|
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);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -196,18 +196,19 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.videoFilePath != null) const SizedBox(height: 8),
|
// https://github.com/jonataslaw/VideoCompress/issues/184
|
||||||
if (widget.videoFilePath != null)
|
// if (widget.videoFilePath != null) const SizedBox(height: 8),
|
||||||
ActionButton(
|
// if (widget.videoFilePath != null)
|
||||||
(videoWithAudio) ? Icons.volume_up_rounded : Icons.volume_off_rounded,
|
// ActionButton(
|
||||||
tooltipText: context.lang.protectAsARealTwonly,
|
// (videoWithAudio) ? Icons.volume_up_rounded : Icons.volume_off_rounded,
|
||||||
color: Colors.white,
|
// tooltipText: context.lang.protectAsARealTwonly,
|
||||||
onPressed: () async {
|
// color: Colors.white,
|
||||||
setState(() {
|
// onPressed: () async {
|
||||||
videoWithAudio = !videoWithAudio;
|
// setState(() {
|
||||||
});
|
// videoWithAudio = !videoWithAudio;
|
||||||
},
|
// });
|
||||||
),
|
// },
|
||||||
|
// ),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
ActionButton(
|
ActionButton(
|
||||||
FontAwesomeIcons.shieldHeart,
|
FontAwesomeIcons.shieldHeart,
|
||||||
|
|
@ -287,6 +288,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||||
isRealTwonly: _isRealTwonly,
|
isRealTwonly: _isRealTwonly,
|
||||||
maxShowTime: maxShowTime,
|
maxShowTime: maxShowTime,
|
||||||
preselectedUser: widget.sendTo,
|
preselectedUser: widget.sendTo,
|
||||||
|
videoFilePath: widget.videoFilePath,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class ShareImageView extends StatefulWidget {
|
||||||
required this.isRealTwonly,
|
required this.isRealTwonly,
|
||||||
required this.maxShowTime,
|
required this.maxShowTime,
|
||||||
this.preselectedUser,
|
this.preselectedUser,
|
||||||
this.videoFilePath,
|
required this.videoFilePath,
|
||||||
this.enableVideoAudio});
|
this.enableVideoAudio});
|
||||||
final Future<Uint8List?> imageBytesFuture;
|
final Future<Uint8List?> imageBytesFuture;
|
||||||
final bool isRealTwonly;
|
final bool isRealTwonly;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue