video_utils.dart 5.95 KB
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_compress/video_compress.dart';
import 'package:video_thumbnail/video_thumbnail.dart';

class VideoUtils {
// 1280*720
  static final int maxVideoPixel = 1280 * 720;
  static final int maxVideoSize = 50;

  /// 清除缓存
  static Future<void> clearTemporaryDirectory() async {
    Directory tempDir = await getTemporaryDirectory();
    if (tempDir == null) return;
    await _delete(tempDir);
  }

  static Future<void> _delete(FileSystemEntity file) async {
    if (file is Directory) {
      final List<FileSystemEntity> children = file.listSync();
      for (final FileSystemEntity child in children) {
        await _delete(child);
      }
    } else {
      await file.delete();
    }
  }

  static getDuration(double duration, {String dateFormat = 'mm:ss'}) {
    int value = duration ~/ 1000; // 毫秒转换为秒;
    int hour = (value) ~/ 3600;
    String hourStr = '${hour}';
    if (hour < 10) {
      //时
      hourStr = "0" + '${hour}';
    }
    int minute = (value % 3600) ~/ 60;
    String minuteStr = '${minute}';
    if (minute < 10) {
      //分
      minuteStr = "0" + '${minute}';
    }
    int second = value % 60;
    String secondStr = '${second}';
    if (second < 10) {
      //秒
      secondStr = "0" + '${second}';
    }
    switch (dateFormat) {
      case 'hh:mm':
        return hourStr + ":" + minuteStr;
        break;
      case 'mm:ss':
        return minuteStr + ":" + secondStr;
        break;
      case 'hh':
        return hourStr;
        break;
      default:
        return hourStr + ":" + minuteStr + ":" + secondStr;
        break;
    }
  }

  // 获取视频的大小(以 MB 为单位)
  static Future<double> getVideoFileSize(String videoPath) async {
    final File file = File(videoPath);
    return file.lengthSync() / 1024 / 1024;
  }

  // 获取视频的像素大小(宽度 * 高度)
  static Future<int> getVideoPixelSize(String videoPath) async {
    final info =
        await VideoCompress.getMediaInfo(videoPath); //视频信息:时长、像素(宽高)、大小、path

    final int width = info.width;
    final int height = info.height;

    return width * height;
  }

  // 获取视频的像素大小(宽度 * 高度)
  // static Future<double> getVideoPixelSize(String videoPath) async {
  //   final VideoPlayerController _controller = VideoPlayerController.file(File(videoPath));
  //   await _controller.initialize();
  //   final double width = _controller.value.size.width;
  //   final double height = _controller.value.size.height;
  //   await _controller.dispose();
  //   return width * height;
  // }
  // 获取视频的封面图
//  static Future<String> getVideoThumbnail(String videoPath) async {
//    final thumbnailPath = await VideoThumbnail.thumbnailFile(
//      video: videoPath,
//      thumbnailPath: (await getTemporaryDirectory()).path,
//      imageFormat: ImageFormat.JPEG,
//      maxHeight: 128,  // 设置最大高度
//      quality: 75, // 设置质量
//    );
//    return thumbnailPath;
//  }
  // 获取视频的封面图
  static Future<String> getThumbnailFile(String url) async {
    // final fileName = await VideoThumbnail.thumbnailFile(
    //   video: url,
    //   thumbnailPath: (await getTemporaryDirectory()).path,
    //   // imageFormat: ImageFormat.WEBP,
    //   // maxHeight:
    //   //     64, // specify the height of the thumbnail, let the width auto-scaled to keep the source aspect ratio
    //   quality: 100,
    // );
    final thumbnail = await VideoThumbnail.thumbnailFile(
      video: url,
      imageFormat: ImageFormat.PNG,
      quality: 100,
    );

    // 获取应用文件夹路径
    String name = DateTime.now().millisecondsSinceEpoch.toString();
    final directory = await getApplicationDocumentsDirectory();
    final String thumbnailPath = '${directory.path}/${name}.png';

    // 将封面图保存到应用文件夹
    final File file = File(thumbnailPath);
    await file.writeAsBytes(await File(thumbnail).readAsBytes());

    // print('Thumbnail saved to $thumbnailPath');

    return thumbnailPath;
  }

  Future<void> copyFile(String oldPath, String newPath) async {
    // 获取应用的临时目录
    final tempDir = await getTemporaryDirectory();
    final newTempPath = '${tempDir.path}/$newPath';

    // 创建新文件的目录
    final newDir =
        Directory(newTempPath.substring(0, newTempPath.lastIndexOf('/')));
    if (!newDir.existsSync()) {
      newDir.createSync(recursive: true);
    }

    // 复制文件到新路径
    final file = File(oldPath);
    await file.copy(newTempPath);

    print('文件已复制到: $newTempPath');
  }

  // Future<String> getTempDirectoryPathWithTimestamp() async {
  //   // 获取临时目录
  //   final tempDir = await getTemporaryDirectory();
  //   // 获取当前时间戳
  //   final timestamp = DateTime.now().millisecondsSinceEpoch;
  //   // 拼接路径和时间戳
  //   final tempPathWithTimestamp = join(tempDir.path, '$timestamp');

  //   return tempPathWithTimestamp;
  // }

  // 是否压缩 (压缩前的校验)
  // 视频像素大小 小于 720p || 视频大小 小于 50mb --> 压缩
  static Future<bool> shouldCompress(String videoPath) async {
    int p = await getVideoPixelSize(videoPath);
    double s = await getVideoFileSize(videoPath); //size
    if (p > maxVideoPixel || s >= maxVideoSize) {
      return true;
    } else {
      return false;
    }
  }

  // 压缩视频的方法
  static Future<File> compress(String videoPath) async {
    // 订阅压缩进度
    // _subscription = VideoCompress.compressProgress$.subscribe((progress) {
    //   _progress = progress;
    //   // 回调进度给外部
    //   if (onProgress != null) {
    //     onProgress!(progress);
    //   }
    // });

    MediaInfo info = await VideoCompress.compressVideo(
      videoPath,
      quality: VideoQuality.Res1280x720Quality,
      deleteOrigin: false,
    );
    return info.file;
  }
}