app-starlock/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart

91 lines
2.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
class VideoThumbnailImage extends StatefulWidget {
final String videoUrl;
const VideoThumbnailImage({Key? key, required this.videoUrl})
: super(key: key);
@override
_VideoThumbnailState createState() => _VideoThumbnailState();
}
class _VideoThumbnailState extends State<VideoThumbnailImage> {
// ✅ 使用 static 缓存:所有实例共享,避免重复请求
static final Map<String, Future<String?>> _pendingThumbnails = {};
late Future<String?> _thumbnailFuture;
@override
void initState() {
super.initState();
// ✅ 如果已存在该 URL 的 Future复用否则创建并缓存
_thumbnailFuture = _pendingThumbnails.putIfAbsent(widget.videoUrl, () {
return _generateThumbnail(widget.videoUrl);
});
}
// 生成缩略图(只执行一次 per URL
Future<String?> _generateThumbnail(String url) async {
try {
final tempDir = await getTemporaryDirectory();
final thumbnail = await VideoThumbnail.thumbnailFile(
video: url,
thumbnailPath: tempDir.path,
imageFormat: ImageFormat.JPEG,
maxHeight: 200,
quality: 100,
);
return thumbnail;
} catch (e) {
print('Failed to generate thumbnail: $e');
return null;
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder<String?>(
future: _thumbnailFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError || !snapshot.hasData) {
return Center(
child: Image.asset(
'images/icon_unHaveData.png',
fit: BoxFit.cover,
),
);
} else {
return Stack(
alignment: Alignment.center,
children: <Widget>[
RotatedBox(
quarterTurns: -1,
child: Image.file(
File(snapshot.data!),
width: 200,
height: 200,
fit: BoxFit.cover,
),
),
Icon(
Icons.play_arrow_rounded,
size: 88.sp,
color: Colors.white.withOpacity(0.8),
),
],
);
}
},
);
}
}