|
|
@@ -10,6 +10,7 @@
|
|
|
#import "ChatsStore.h"
|
|
|
#import "AVFoundation/AVFoundation.h"
|
|
|
#import "FileNetApi.h"
|
|
|
+#import <SDWebImage/SDImageCache.h>
|
|
|
|
|
|
@implementation ChatMessageModel
|
|
|
|
|
|
@@ -276,15 +277,39 @@
|
|
|
}
|
|
|
|
|
|
- (void)generateThumbnailWithCompletion:(void(^)(UIImage *thumbnail))completion {
|
|
|
+ // 如果内存中已有缩略图,直接返回
|
|
|
if (self.videoThumbnailImage) {
|
|
|
if (completion) completion(self.videoThumbnailImage);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 生成缓存 key,优先使用 msgId,如果没有则使用 URL 的 hash
|
|
|
+ NSString *cacheKey = nil;
|
|
|
+ if (self.msgId.length > 0) {
|
|
|
+ cacheKey = [NSString stringWithFormat:@"video_thumbnail_%@", self.msgId];
|
|
|
+ } else if (self.url.length > 0) {
|
|
|
+ cacheKey = [NSString stringWithFormat:@"video_thumbnail_%lu", (unsigned long)[self.url hash]];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从 SDWebImage 缓存中查找
|
|
|
+ if (cacheKey) {
|
|
|
+ SDImageCache *imageCache = [SDImageCache sharedImageCache];
|
|
|
+ UIImage *cachedImage = [imageCache imageFromCacheForKey:cacheKey];
|
|
|
+ if (cachedImage) {
|
|
|
+ NSLog(@"从缓存加载缩略图: %@", cacheKey);
|
|
|
+ self.videoThumbnailImage = cachedImage;
|
|
|
+ if (completion) completion(cachedImage);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 没有缓存,需要生成缩略图
|
|
|
NSURL *videoURL = nil;
|
|
|
if (self.localurl.length != 0 && [[NSFileManager defaultManager] fileExistsAtPath:self.localurl]) {
|
|
|
+ // 从本地文件生成缩略图
|
|
|
NSLog(@"generateThumbnailWithCompletion localurl:%@",self.localurl);
|
|
|
videoURL = [NSURL fileURLWithPath:self.localurl];
|
|
|
+ NSString *finalCacheKey = cacheKey;
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
|
|
|
|
|
|
@@ -298,51 +323,66 @@
|
|
|
if (!error && imageRef) {
|
|
|
UIImage *thumbnail = [[UIImage alloc] initWithCGImage:imageRef];
|
|
|
CGImageRelease(imageRef);
|
|
|
+
|
|
|
// 缓存到内存
|
|
|
self.videoThumbnailImage = thumbnail;
|
|
|
|
|
|
+ // 使用 SDWebImage 缓存到磁盘和内存
|
|
|
+ if (finalCacheKey) {
|
|
|
+ SDImageCache *imageCache = [SDImageCache sharedImageCache];
|
|
|
+ [imageCache storeImage:thumbnail forKey:finalCacheKey completion:^{
|
|
|
+ NSLog(@"缩略图已缓存: %@", finalCacheKey);
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
if (completion){
|
|
|
completion(thumbnail);
|
|
|
}
|
|
|
} else {
|
|
|
-
|
|
|
if (completion) completion(nil);
|
|
|
}
|
|
|
});
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
+ // 从远程 URL 生成缩略图
|
|
|
NSLog(@"generateThumbnailWithCompletion url");
|
|
|
if (self.url.length == 0){
|
|
|
- completion(nil);
|
|
|
+ if (completion) completion(nil);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
NSDictionary *options = @{AVURLAssetAllowsCellularAccessKey: @YES,
|
|
|
- AVURLAssetPreferPreciseDurationAndTimingKey: @YES};
|
|
|
+ AVURLAssetPreferPreciseDurationAndTimingKey: @YES};
|
|
|
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:getURL(self.url) options:options];
|
|
|
-
|
|
|
- // 创建图像生成器
|
|
|
- AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
|
|
|
- generator.appliesPreferredTrackTransform = YES; // 应用视频的方向
|
|
|
- generator.maximumSize = CGSizeMake(320, 0); // 设置最大尺寸,保持宽高比
|
|
|
-
|
|
|
- // 异步生成缩略图
|
|
|
- [generator generateCGImagesAsynchronouslyForTimes:@[[NSValue valueWithCMTime:kCMTimeZero]]
|
|
|
- completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
|
|
|
- __block UIImage *thumbnail = nil;
|
|
|
- // 处理生成结果
|
|
|
- if (result == AVAssetImageGeneratorSucceeded && image) {
|
|
|
- // 创建UIImage,注意CGImageCreateCopy不是必需的
|
|
|
- thumbnail = [UIImage imageWithCGImage:image];
|
|
|
- self.videoThumbnailImage = thumbnail;
|
|
|
- // 重要:虽然UIImage会retain CGImageRef,但最佳实践是手动管理
|
|
|
- // 这里不需要调用CGImageRelease,因为imageWithCGImage会自动retain
|
|
|
+
|
|
|
+ // 创建图像生成器
|
|
|
+ AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
|
|
|
+ generator.appliesPreferredTrackTransform = YES; // 应用视频的方向
|
|
|
+ generator.maximumSize = CGSizeMake(320, 0); // 设置最大尺寸,保持宽高比
|
|
|
+
|
|
|
+ NSString *finalCacheKey = cacheKey;
|
|
|
+ // 异步生成缩略图
|
|
|
+ [generator generateCGImagesAsynchronouslyForTimes:@[[NSValue valueWithCMTime:kCMTimeZero]]
|
|
|
+ completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
|
|
|
+ __block UIImage *thumbnail = nil;
|
|
|
+ // 处理生成结果
|
|
|
+ if (result == AVAssetImageGeneratorSucceeded && image) {
|
|
|
+ // 创建UIImage
|
|
|
+ thumbnail = [UIImage imageWithCGImage:image];
|
|
|
+ self.videoThumbnailImage = thumbnail;
|
|
|
+
|
|
|
+ // 使用 SDWebImage 缓存到磁盘和内存
|
|
|
+ if (finalCacheKey) {
|
|
|
+ SDImageCache *imageCache = [SDImageCache sharedImageCache];
|
|
|
+ [imageCache storeImage:thumbnail forKey:finalCacheKey completion:^{
|
|
|
+ NSLog(@"缩略图已缓存: %@", finalCacheKey);
|
|
|
+ }];
|
|
|
}
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- if (completion) completion(thumbnail);
|
|
|
- });
|
|
|
- }];
|
|
|
+ }
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+ if (completion) completion(thumbnail);
|
|
|
+ });
|
|
|
+ }];
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
//下载视频文件
|