1+ import 'dart:convert' ;
12import 'dart:math' ;
23
34import 'package:dio/dio.dart' ;
@@ -12,9 +13,12 @@ import 'package:flyer_chat_image_message/flyer_chat_image_message.dart';
1213import 'package:flyer_chat_system_message/flyer_chat_system_message.dart' ;
1314import 'package:flyer_chat_text_message/flyer_chat_text_message.dart' ;
1415import 'package:flyer_chat_video_message/flyer_chat_video_message.dart' ;
16+ import 'package:image/image.dart' as img;
1517import 'package:image_picker/image_picker.dart' ;
1618import 'package:pull_down_button/pull_down_button.dart' ;
19+ import 'package:thumbhash/thumbhash.dart' show rgbaToThumbHash;
1720import 'package:uuid/uuid.dart' ;
21+ import 'package:video_thumbnail/video_thumbnail.dart' ;
1822
1923import 'create_message.dart' ;
2024import 'widgets/composer_action_bar.dart' ;
@@ -417,44 +421,129 @@ class LocalState extends State<Local> {
417421 title: const Text ('Video' ),
418422 onTap: () async {
419423 Navigator .pop (context);
420- // Uncomment to use proper path
421- // Hardcoding for testing since the simulator library doesn't expose video files
424+ // Uncomment to use picker instead of hardcoding the video url
422425
423426 final picker = ImagePicker ();
424427 final result = await picker.pickVideo (
425428 source: ImageSource .gallery,
426429 );
427430
428431 if (result != null ) {
429- // Optionally get the file size
430- // final fileSizeInBytes = await result.length();
431- // Note to get the height/width of the video, you can use the following:
432- // final controller = VideoPlayerController.file(file);
433- // await controller.initialize();
434- // final width = controller.value.size.width;
435- // final height = controller.value.size.height;
432+ String ? thumbHash;
433+ int ? width;
434+ int ? height;
435+ int ? fileSizeInBytes;
436+ try {
437+ // Optionally get the file size
438+ fileSizeInBytes = await result.length ();
439+
440+ // Get the video width and height
441+ final fullSizeimageBytes =
442+ await VideoThumbnail .thumbnailData (
443+ video: result.path,
444+ imageFormat: ImageFormat .WEBP ,
445+ quality: 1 ,
446+ );
447+
448+ final fullSizedecoded = img.decodeImage (
449+ fullSizeimageBytes! ,
450+ );
451+ if (fullSizedecoded != null ) {
452+ width = fullSizedecoded.width;
453+ height = fullSizedecoded.height;
454+ }
455+
456+ // Generate the thumbhash
457+ final thumbSizeImageBytes =
458+ await VideoThumbnail .thumbnailData (
459+ video: result.path,
460+ imageFormat: ImageFormat .WEBP ,
461+ maxWidth: 100 ,
462+ maxHeight: 100 ,
463+ quality: 25 ,
464+ );
465+ final decoded = img.decodeImage (thumbSizeImageBytes! );
466+ if (decoded != null ) {
467+ final thumbHashBytes = rgbaToThumbHash (
468+ decoded.width,
469+ decoded.height,
470+ decoded.getBytes (),
471+ );
472+
473+ thumbHash = base64.encode (thumbHashBytes);
474+ }
475+ } catch (e) {
476+ debugPrint (e.toString ());
477+ }
436478
437479 // Create a proper file message
438480 final videoMessage = VideoMessage (
439481 id: _uuid.v4 (),
440482 authorId: _currentUser.id,
441483 createdAt: DateTime .now ().toUtc (),
442484 sentAt: DateTime .now ().toUtc (),
443- // Uncomment to use proper path
444- // Hardcoding for testing since the simulator library doesn't expose video files
445485 source: result.path,
446-
447- // size: fileSizeInBytes,
486+ thumbhash: thumbHash,
487+ width: width? .toDouble (),
488+ height: height? .toDouble (),
489+ size: fileSizeInBytes,
448490 );
449491 await _chatController.insertMessage (videoMessage);
450492 }
451493
494+ // const videoUrl =
495+ // 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4';
496+ // String? thumbHash;
497+ // int? width;
498+ // int? height;
499+ // try {
500+ // // Get the video width and height
501+ // final fullSizeimageBytes =
502+ // await VideoThumbnail.thumbnailData(
503+ // video: videoUrl,
504+ // imageFormat: ImageFormat.WEBP,
505+ // quality: 1,
506+ // );
507+
508+ // final fullSizedecoded = img.decodeImage(
509+ // fullSizeimageBytes!,
510+ // );
511+ // if (fullSizedecoded != null) {
512+ // width = fullSizedecoded.width;
513+ // height = fullSizedecoded.height;
514+ // }
515+
516+ // // Generate the thumbhash
517+ // final thumbSizeImageBytes =
518+ // await VideoThumbnail.thumbnailData(
519+ // video: videoUrl,
520+ // imageFormat: ImageFormat.WEBP,
521+ // maxWidth: 100,
522+ // maxHeight: 100,
523+ // quality: 25,
524+ // );
525+ // final decoded = img.decodeImage(thumbSizeImageBytes!);
526+ // if (decoded != null) {
527+ // final thumbHashBytes = rgbaToThumbHash(
528+ // decoded.width,
529+ // decoded.height,
530+ // decoded.getBytes(),
531+ // );
532+
533+ // thumbHash = base64.encode(thumbHashBytes);
534+ // }
535+ // } catch (e) {
536+ // debugPrint(e.toString());
537+ // }
538+
452539 // final videoMessage = VideoMessage(
453540 // id: _uuid.v4(),
454541 // authorId: _currentUser.id,
455542 // createdAt: DateTime.now().toUtc(),
456- // source:
457- // 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
543+ // source: videoUrl,
544+ // thumbhash: thumbHash,
545+ // width: width?.toDouble(),
546+ // height: height?.toDouble(),
458547 // );
459548 // await _chatController.insertMessage(videoMessage);
460549 },
0 commit comments