在iOS上将视频转换为动画GIF

时间:2015-09-07 21:22:12

标签: ios animated-gif

我想转换使用相机拍摄的视频文件(.mp4)并将其转换为动画GIF图像。

我查看了Apple Docs,但似乎没有任何内置功能。<​​/ p>

我该如何处理这项任务?

3 个答案:

答案 0 :(得分:2)

没有内置的API。我发布了一个将视频文件转换为动画GIF图像的库,同时提供足够的灵活性来调整帧速率,帧持续时间,大小等设置。

该库名为NSGIF。您可以在此处找到它:http://github.com/NSRare/NSGIF

这是将视频转换为GIF的最简单方法:

[NSGIF optimalGIFfromURL:url loopCount:0 completion:^(NSURL *GifURL) {
    NSLog(@"Finished generating GIF: %@", GifURL);
}];

使用optimalGIFfromURL方法,根据最佳设置自动生成GIF。还有更大的灵活性。查看回购以获取更多样品。

答案 1 :(得分:2)

你可以在Some Step中完成 1- 计算所需的框架

CMTime vid_length = asset.duration;
float seconds = CMTimeGetSeconds(vid_length);
int required_frames_count = seconds * 12.5; //You can set according 

到你

int64_t step = vid_length.value / required_frames_count;
int value = 0;

2- 制作GIF文件设置属性

destination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path],
                                                                        kUTTypeGIF,
                                                                        required_frames_count,
                                                                        NULL);

   frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0.8] forKey:(NSString *)kCGImagePropertyGIFDelayTime]
                                                                forKey:(NSString *)kCGImagePropertyGIFDictionary];


    gifProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount]
                                                              forKey:(NSString *)kCGImagePropertyGIFDictionary];

第3步 从视频资产AVAssetImageGenerator生成帧

 for (int i = 0; i < required_frames_count; i++) {

        AVAssetImageGenerator *image_generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
        image_generator.requestedTimeToleranceAfter = kCMTimeZero;
        image_generator.requestedTimeToleranceBefore = kCMTimeZero;
        image_generator.appliesPreferredTrackTransform = YES;

        image_generator.maximumSize = CGSizeMake(wd, ht);    //to get an unscaled image or define a bounding box of 640px, aspect ratio remains

        CMTime time = CMTimeMake(value, vid_length.timescale);
        CGImageRef image_ref = [image_generator copyCGImageAtTime:time actualTime:NULL error:NULL];
        UIImage *thumb = [UIImage imageWithCGImage:image_ref];


        [self mergeFrameForGif:thumb];


        CGImageRelease(image_ref);
        value += step;


    }
    NSLog(@"Over all Size of Image(bytes):%ld",t);


    CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifProperties);
    CGImageDestinationFinalize(destination);
    CFRelease(destination);
    NSLog(@"animated GIF file created at %@", path);

第4步 在Gif文件中添加框架

- (void)mergeFrameForGif:(UIImage*)pic1
{
    CGImageDestinationAddImage(destination, pic1.CGImage, (CFDictionaryRef)frameProperties);
    pic1=nil;

}

答案 2 :(得分:0)

已为Swift 5.1更新

import Foundation
import AVFoundation
import PhotosUI
import MobileCoreServices

func makeGIF(asset: AVAsset, destionationURL: URL, width: CGFloat, height: CGFloat) {


let duration = asset.duration

let vid_length : CMTime = duration

let seconds : Double = CMTimeGetSeconds(vid_length)

let tracks = asset.tracks(withMediaType: .video)

let fps = tracks.first?.nominalFrameRate ?? 1.0

let required_frames_count : Int = Int(seconds * Double(fps)) // You can set according

let step : Int64 = vid_length.value / Int64(required_frames_count)

var value : CMTimeValue = CMTimeValue.init(0.0)

let destination = CGImageDestinationCreateWithURL(destionationURL as CFURL, kUTTypeGIF, required_frames_count, nil)

let gifProperties : CFDictionary = [ kCGImagePropertyGIFDictionary : [kCGImagePropertyGIFLoopCount : 0] ] as CFDictionary

for _ in 0 ..< required_frames_count {
    
    let image_generator : AVAssetImageGenerator = AVAssetImageGenerator.init(asset: asset)
    
    image_generator.requestedTimeToleranceAfter = CMTime.zero
    image_generator.requestedTimeToleranceBefore = CMTime.zero
    image_generator.appliesPreferredTrackTransform = true
    
    // to get an unscaled image or define a bounding box of 640px, aspect ratio remains
    
    image_generator.maximumSize = CGSize(width: width, height: height)
    
    let time : CMTime = CMTime(value: value, timescale: vid_length.timescale)
    
    do {
        
        let image_ref : CGImage = try image_generator.copyCGImage(at: time, actualTime: nil)
        
        let thumb : UIImage = UIImage.init(cgImage: image_ref)
        
        
        mergeFrameForGif(frame: thumb, destination: destination!)
        
        value = value + step
        
    } catch {
        
        //
        
    }
    
}

//print("Overall Size of Image(bytes): \(t)")


CGImageDestinationSetProperties(destination!, gifProperties)
CGImageDestinationFinalize(destination!)

print("animated GIF file created at \(destionationURL)")
    
}


func mergeFrameForGif(frame: UIImage, destination: CGImageDestination) {


let frameProperties : CFDictionary = [ kCGImagePropertyGIFDictionary : [kCGImagePropertyGIFDelayTime : 0.8] ] as CFDictionary

CGImageDestinationAddImage(destination, frame.cgImage!, frameProperties)


}