AVAssetExtension.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import AVKit
  2. extension AVAsset {
  3. func countFrames(exact:Bool) -> Int {
  4. var frameCount = 0
  5. if let videoReader = try? AVAssetReader(asset: self) {
  6. if let videoTrack = self.tracks(withMediaType: .video).first {
  7. frameCount = Int(CMTimeGetSeconds(self.duration) * Float64(videoTrack.nominalFrameRate))
  8. if exact {
  9. frameCount = 0
  10. let videoReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: nil)
  11. videoReader.add(videoReaderOutput)
  12. videoReader.startReading()
  13. // count frames
  14. while true {
  15. let sampleBuffer = videoReaderOutput.copyNextSampleBuffer()
  16. if sampleBuffer == nil {
  17. break
  18. }
  19. frameCount += 1
  20. }
  21. videoReader.cancelReading()
  22. }
  23. }
  24. }
  25. return frameCount
  26. }
  27. func stillImageTime() -> CMTime? {
  28. var stillTime:CMTime? = nil
  29. if let videoReader = try? AVAssetReader(asset: self) {
  30. if let metadataTrack = self.tracks(withMediaType: .metadata).first {
  31. let videoReaderOutput = AVAssetReaderTrackOutput(track: metadataTrack, outputSettings: nil)
  32. videoReader.add(videoReaderOutput)
  33. videoReader.startReading()
  34. let keyStillImageTime = "com.apple.quicktime.still-image-time"
  35. let keySpaceQuickTimeMetadata = "mdta"
  36. var found = false
  37. while found == false {
  38. if let sampleBuffer = videoReaderOutput.copyNextSampleBuffer() {
  39. if CMSampleBufferGetNumSamples(sampleBuffer) != 0 {
  40. let group = AVTimedMetadataGroup(sampleBuffer: sampleBuffer)
  41. for item in group?.items ?? [] {
  42. if item.key as? String == keyStillImageTime && item.keySpace!.rawValue == keySpaceQuickTimeMetadata {
  43. stillTime = group?.timeRange.start
  44. //print("stillImageTime = \(CMTimeGetSeconds(stillTime!))")
  45. found = true
  46. break
  47. }
  48. }
  49. }
  50. }
  51. else {
  52. break;
  53. }
  54. }
  55. videoReader.cancelReading()
  56. }
  57. }
  58. return stillTime
  59. }
  60. func makeStillImageTimeRange(percent:Float, inFrameCount:Int = 0) -> CMTimeRange {
  61. var time = self.duration
  62. var frameCount = inFrameCount
  63. if frameCount == 0 {
  64. frameCount = self.countFrames(exact: true)
  65. }
  66. let frameDuration = Int64(Float(time.value) / Float(frameCount))
  67. time.value = Int64(Float(time.value) * percent)
  68. //print("stillImageTime = \(CMTimeGetSeconds(time))")
  69. return CMTimeRangeMake(start: time, duration: CMTimeMake(value: frameDuration, timescale: time.timescale))
  70. }
  71. func getAssetFrame(percent:Float) -> UIImage?
  72. {
  73. let imageGenerator = AVAssetImageGenerator(asset: self)
  74. imageGenerator.appliesPreferredTrackTransform = true
  75. imageGenerator.requestedTimeToleranceAfter = CMTimeMake(value: 1,timescale: 100)
  76. imageGenerator.requestedTimeToleranceBefore = CMTimeMake(value: 1,timescale: 100)
  77. var time = self.duration
  78. time.value = Int64(Float(time.value) * percent)
  79. do {
  80. var actualTime = CMTime.zero
  81. let imageRef = try imageGenerator.copyCGImage(at: time, actualTime:&actualTime)
  82. let img = UIImage(cgImage: imageRef)
  83. return img
  84. }
  85. catch let error as NSError
  86. {
  87. print("Image generation failed with error \(error)")
  88. return nil
  89. }
  90. }
  91. }