17 changed files with 360 additions and 86 deletions
-
4kplayer.xcodeproj/project.pbxproj
-
8kplayer/AppDelegate.swift
-
39kplayer/core/ItemModel.swift
-
31kplayer/core/MediaItem.swift
-
1kplayer/core/MediaModel.swift
-
78kplayer/core/NetworkManager.swift
-
2kplayer/core/ThumbnailCache.swift
-
9kplayer/detail/DetailViewController.swift
-
37kplayer/detail/VideoController.swift
-
49kplayer/master/MasterViewController.swift
-
57kplayer/master/NetworkDelegate.swift
-
16kplayer/photo/PhotoController.swift
-
2kplayer/readme.md
-
27kplayer/util/FileHelper.swift
-
4kplayer/util/UploadOperation.swift
-
64kplayer/util/VideoHelper.swift
-
16kplayer/util/stringutil.swift
@ -0,0 +1,64 @@ |
|||
// |
|||
// Created by Marco Schmickler on 30.04.21. |
|||
// Copyright (c) 2021 Marco Schmickler. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import AVFoundation |
|||
|
|||
class VideoHelper { |
|||
public static func export(item: AVPlayerItem, clipStart: Double, clipDuration: Double, file: URL, completion: @escaping (URL?) -> ()) { |
|||
guard item.asset.isExportable else { |
|||
completion(nil) |
|||
return |
|||
} |
|||
|
|||
let composition = AVMutableComposition() |
|||
let compositionVideoTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) |
|||
let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) |
|||
|
|||
let sourceVideoTrack = item.asset.tracks(withMediaType: AVMediaType.video).first! |
|||
let sourceAudioTrack = item.asset.tracks(withMediaType: AVMediaType.audio).first! |
|||
let start = CMTime(seconds: clipStart, preferredTimescale: 1); |
|||
let dur = CMTime(seconds: clipDuration, preferredTimescale: 100); |
|||
do { |
|||
|
|||
try compositionVideoTrack!.insertTimeRange(CMTimeRangeMake(start: start, duration: dur), of: sourceVideoTrack, at: start) |
|||
try compositionAudioTrack!.insertTimeRange(CMTimeRangeMake(start: start, duration: dur), of: sourceAudioTrack, at: start) |
|||
} catch(_) { |
|||
completion(nil) |
|||
return |
|||
} |
|||
|
|||
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: composition) |
|||
var preset: String = AVAssetExportPresetPassthrough |
|||
// if compatiblePresets.contains(AVAssetExportPreset3840x2160) { preset = AVAssetExportPreset3840x2160 } |
|||
|
|||
guard |
|||
let exportSession = AVAssetExportSession(asset: composition, presetName: preset), |
|||
exportSession.supportedFileTypes.contains(AVFileType.mp4) else { |
|||
completion(nil) |
|||
return |
|||
} |
|||
|
|||
exportSession.outputURL = file |
|||
exportSession.outputFileType = AVFileType.mp4 |
|||
let startTime = CMTime(seconds: 0.0, preferredTimescale: 100); |
|||
let timeRange = CMTimeRangeMake(start: start, duration: dur) |
|||
exportSession.timeRange = timeRange |
|||
|
|||
print("Write file \(file)") |
|||
do { |
|||
try FileManager.default.removeItem(at: file) |
|||
} catch { |
|||
} |
|||
exportSession.exportAsynchronously { |
|||
print("ready \(exportSession.error)") |
|||
// let data = try? Data(contentsOf: tempFileUrl) |
|||
// _ = try? FileManager.default.removeItem(at: tempFileUrl) |
|||
let r = FileManager.default.fileExists(atPath: file.absoluteString) |
|||
print (r) |
|||
completion(file) |
|||
} |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue