【问题标题】:Convert video to animated GIF on iOS在 iOS 上将视频转换为动画 GIF
【发布时间】:2015-12-03 10:53:27
【问题描述】:

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

我查阅了 Apple Docs,似乎没有任何内置函数。

我应该如何完成这项任务?

【问题讨论】:

  • 为什么要使用 GIF?它会生成带有非常有限的调色板的巨大图像文件!
  • 为什么 iOS 会为您提供一种将 mp4 转换为 gif 的方法?那只会产生开销,并且会使您的应用程序膨胀。使用专用的视频编辑应用程序(After Effects 等...)将其转换为图像序列。
  • @jtbandes,我知道 .GIF 的缺点,但当前项目需要它用于 web 端。
  • @the_critic,我说的是数百个用户提供的视频。在 Ae 中编辑每一个都不是最优化的解决方案:)
  • @pixthecoder 哦,没想到这一点,对不起......很遗憾,我不能帮助你。

标签: ios animated-gif


【解决方案1】:

为 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)


}

【讨论】:

    【解决方案2】:

    您可以在某些步骤中做到这一点 1- 计算所需的Frame

    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;
    
    }
    

    【讨论】:

      【解决方案3】:

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

      该库名为NSGIF。你可以在这里找到它:http://github.com/NSRare/NSGIF

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

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

      使用optimalGIFfromURL 方法,根据最佳设置自动生成GIF。还有更多灵活性的空间。查看 repo 以获取更多示例。

      【讨论】:

      猜你喜欢
      • 2014-04-19
      • 2020-03-17
      • 2017-04-20
      • 1970-01-01
      • 2017-04-05
      • 1970-01-01
      • 2017-04-07
      相关资源
      最近更新 更多