美文网首页
视频转码gif

视频转码gif

作者: seventhboy | 来源:发表于2020-02-13 10:32 被阅读0次

    heTranscodeOperation ()
    @property (assign, nonatomic) BOOL executing;//判断NSOperation是否执行
    @property (assign, nonatomic) BOOL finished;//判断NSOperation是否结束

    @property (nonatomic,copy)NSString *diskCachePath;//
    @property (nonatomic,copy)NSString *fileName;//沙盒文件名称

    @property (nonatomic, copy) DownloaderCancelBlock completedBlock; //下载完成回调block

    @end

    @implementation HGVideoCacheTranscodeOperation
    @synthesize executing = _executing;
    @synthesize finished = _finished;

    • (instancetype)initWithPath:(NSString *)diskCachePath fileName:(NSString *)fileName completedBlock:(DownloaderCancelBlock)completedBlock{
      self = [super init];
      if (self) {
      _diskCachePath = [diskCachePath copy];
      _fileName = [fileName copy];
      _completedBlock = [completedBlock copy];
      }
      return self;
      }

    • (void)start {
      [self willChangeValueForKey:@"isExecuting"];
      _executing = YES;
      [self didChangeValueForKey:@"isExecuting"];

        //判断任务执行前是否取消了任务
      

      if (self.isCancelled) {
      [self done];
      return;
      }
      [self videoTranscodingWithPath:self.diskCachePath fileName:self.fileName completedBlock:self.completedBlock];

    }

    -(BOOL)isExecuting {
    return _executing;
    }

    • (BOOL)isFinished {
      return _finished;
      }

    • (BOOL)isAsynchronous {
      return YES;
      }

    //取消任务
    -(void)cancel {
    @synchronized (self) {
    [self done];
    }
    }
    //更新任务状态

    • (void)done {
      [super cancel];
      if(_executing) {
      [self willChangeValueForKey:@"isFinished"];
      [self willChangeValueForKey:@"isExecuting"];
      _finished = YES;
      _executing = NO;
      [self didChangeValueForKey:@"isFinished"];
      [self didChangeValueForKey:@"isExecuting"];
      [self reset];
      }

    }

    //重置请求数据

    • (void)reset {
      if (self.completedBlock) {
      self.completedBlock = nil;
      }
      }

    pragma mark - 视频转gif -

    -(void)videoTranscodingWithPath:(NSString *)diskCachePath fileName:(NSString *)fileName completedBlock:(DownloaderCancelBlock)completedBlock{
    NSString *videoPath = [[diskCachePath stringByAppendingPathComponent:fileName] stringByAppendingString:KVideoSuffix];
    NSURL *videoURL = [NSURL fileURLWithPath:videoPath];
    NSLog(@"存在文件:\n%@",videoURL);

    AVURLAsset *asset = [AVURLAsset assetWithURL:videoURL];
    AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
    generator.appliesPreferredTrackTransform = YES;
    generator.requestedTimeToleranceBefore = kCMTimeZero;
    generator.requestedTimeToleranceAfter = kCMTimeZero;
    
        //视频宽高
    AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
    CGSize videoSize = CGSizeApplyAffineTransform(videoTrack.naturalSize, videoTrack.preferredTransform);
    videoSize = CGSizeMake(fabs(videoSize.width), fabs(videoSize.height));
    generator.maximumSize = videoSize;
    
    NSArray *indexes = [self generateOffsets:asset];
    NSLog(@"%li",(unsigned long)[indexes count]);
    
    NSMutableDictionary *images = [NSMutableDictionary dictionaryWithCapacity:[indexes count]];
    
    CMTime actualTime;
    for (NSNumber *number in indexes) {
        if (self.isCancelled) {
            [self done];
            return;
        }
    
        double offset = [number doubleValue];
        NSLog(@"%f",offset);
        if (offset < 0 || offset > CMTimeGetSeconds(asset.duration)) {
            continue;
        }
        CMTime t = CMTimeMakeWithSeconds(offset, (int)[indexes count]);
        NSError *error = nil;
        CGImageRef source = [generator copyCGImageAtTime:t actualTime:nil error:&error];
        if (!source) {
            NSLog(@"Error copying image at index %f: %@", CMTimeGetSeconds(actualTime), [error localizedDescription]);
            return;
        }
        [images setObject:CFBridgingRelease(source) forKey:number];
    }
    if (self.isCancelled) {
        [self done];
        return;
    }
    NSMutableArray *strip =[NSMutableArray array];
    if (images) {
        NSArray *times = [self generateOffsets:asset];
        for (int idx = 0; idx < [times count]; idx++) {
            NSNumber *time = [times objectAtIndex:idx];
            CGImageRef image = (__bridge CGImageRef)([images objectForKey:time]);
            [strip addObject:[UIImage imageWithCGImage:image]];
            NSLog(@"%d",idx);
        }
    
            //转码
        @weakify(self)
        [self writeImageAsGIF:strip toPath:videoPath callbackBlock:^{
            @strongify(self)
            self.completedBlock();
            [self done];
        }];
    }
    

    }

    //时间个数

    • (NSArray *) generateOffsets:(AVAsset *)asset{
      double duration = CMTimeGetSeconds(asset.duration);
      NSMutableArray *indexes = [NSMutableArray array];
      double time = 0.0f;
      while (time < duration) {
      [indexes addObject:[NSNumber numberWithDouble:time]];
      time +=0.1;
      }
      return indexes;
      }

    ///绘制gif
    -(void)writeImageAsGIF:(NSArray )images
    toPath:(NSString
    )path
    callbackBlock:(dispatch_block_t)callbackBlock {
    if ([ [NSFileManager defaultManager] fileExistsAtPath:path]){
    [[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
    }
    path = [path stringByReplacingOccurrencesOfString:KVideoSuffix withString:KGifSuffix];
    CGFloat secondsPerFrameFloat = 1 / 30;
    NSNumber * secondsPerFrame = [NSNumber numberWithFloat:secondsPerFrameFloat];//30帧

    NSDictionary * gifDict = [NSDictionary dictionaryWithObject:secondsPerFrame
                                                         forKey:( NSString *)kCGImagePropertyGIFDelayTime] ;
    
    NSDictionary *prep = [NSDictionary dictionaryWithObject:gifDict
                                                     forKey:(NSString *)kCGImagePropertyGIFDictionary];
    
    NSDictionary *fileProperties = @{
                        (__bridge id)kCGImagePropertyGIFDictionary: @{
                            (__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever
                        }
                    };
    
    CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:path];
    
    CGImageDestinationRef dst = CGImageDestinationCreateWithURL(url, kUTTypeGIF, [images count], nil);
    CGImageDestinationSetProperties(dst, (__bridge CFDictionaryRef)fileProperties);
    
    for (int i=0;i<[images count];i++){
        UIImage * anImage = [images objectAtIndex:i];
        CGImageDestinationAddImage(dst, anImage.CGImage,(__bridge CFDictionaryRef)(prep));
    }
    
    bool fileSave = CGImageDestinationFinalize(dst);
    CFRelease(dst);
    if(fileSave) {
        NSLog(@"animated GIF file created at %@", path);
        if ([ [NSFileManager defaultManager] fileExistsAtPath:path]){
            CGFloat gif = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileSize];
            NSLog(@" hehe%lf",gif);
        }
    }else{
        NSLog(@"error: no animated GIF file created at %@", path);
    }
    
    !callbackBlock?:callbackBlock();
    

    }

    @end

    相关文章

      网友评论

          本文标题:视频转码gif

          本文链接:https://www.haomeiwen.com/subject/mwdkfhtx.html