Какой наиболее эффективный способ объединить два или более видео в одно в приложении iOS? Я пробовал использовать AVFoundation, но он работает довольно медленно.
Я пробовал разные пресеты (даже AVAssetExportPreset1280x720), но процесс все равно очень медленный.
Есть ли какие-либо инфраструктуры или методы с ускорением на графическом процессоре, которые могут повысить производительность?
Вот моя текущая реализация.
func mergeVideos(
_ items: [VideoItem],
presetName: String,
overlay: Overlay?,
completionHandler: @escaping (Result) -> Void
) {
let fileName = "video-\(Date().description)"
let composition = AVMutableComposition()
let allItemsAreMuted = items.allSatisfy(\.isMuted)
guard
let compVideoTrack = composition.addMutableTrack(
withMediaType: .video,
preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)
)
else {
return completionHandler(.failure(VideoEditorError.unknown))
}
var compAudioTrack: AVMutableCompositionTrack?
if !allItemsAreMuted {
compAudioTrack = composition.addMutableTrack(
withMediaType: .audio,
preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)
)
if compAudioTrack == nil {
return completionHandler(.failure(VideoEditorError.unknown))
}
}
var currentTime = CMTime.zero
var loadedVideoTracks = [AVAsset: AVAssetTrack]()
var loadedAudioTracks = [AVAsset: AVAssetTrack]()
items.forEach { item in
do {
var audioTrack: AVAssetTrack?
let range = item.range ?? CMTimeRangeMake(start: CMTime.zero, duration: item.asset.duration)
var scaledDuration: CMTime?
if let rate = item.rate, rate != 1 {
scaledDuration = CMTime(seconds: range.duration.seconds / Double(rate), preferredTimescale: 1000)
}
if let videoTrack = loadedVideoTracks[item.asset] ?? item.asset.tracks(withMediaType: .video).first {
loadedVideoTracks[item.asset] = videoTrack
try compVideoTrack.insertTimeRange(range, of: videoTrack, at: currentTime)
}
if !item.isMuted {
audioTrack = loadedAudioTracks[item.asset] ?? item.asset.tracks(withMediaType: .audio).first
if let audioTrack = audioTrack {
loadedAudioTracks[item.asset] = audioTrack
try compAudioTrack?.insertTimeRange(range, of: audioTrack, at: currentTime)
}
}
if let scaledDuration = scaledDuration {
let currentRange = CMTimeRangeMake(start: currentTime, duration: range.duration)
compVideoTrack.scaleTimeRange(currentRange, toDuration: scaledDuration)
compAudioTrack?.scaleTimeRange(currentRange, toDuration: scaledDuration)
}
currentTime = CMTimeAdd(currentTime, scaledDuration ?? range.duration)
} catch {
completionHandler(.failure(error))
return
}
}
let exportURL = URL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent(fileName)
.appendingPathExtension("mov")
guard let export = AVAssetExportSession(
asset: composition,
presetName: presetName
) else {
completionHandler(.failure(VideoEditorError.unknown))
return
}
if let overlay = overlay {
let videoInfo = orientation(from: loadedVideoTracks.first!.value.preferredTransform)
let videoSize: CGSize
if videoInfo.isPortrait {
videoSize = CGSize(
width: loadedVideoTracks.first!.value.naturalSize.height,
height: loadedVideoTracks.first!.value.naturalSize.width
)
} else {
videoSize = loadedVideoTracks.first!.value.naturalSize
}
let overlayLayer = CALayer()
overlayLayer.contents = overlay.image.cgImage
overlayLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
overlayLayer.opacity = 1
overlayLayer.masksToBounds = true
overlayLayer.transform = CATransform3DMakeTranslation(overlay.rotationDegrees, 0, 0)
let radians = CGFloat(overlay.rotationDegrees) * .pi / 180.0
overlayLayer.transform = CATransform3DMakeRotation(radians, 1, 0, 0)
let videoLayer = CALayer()
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
let animationLayer = CALayer()
animationLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
animationLayer.addSublayer(videoLayer)
animationLayer.addSublayer(overlayLayer)
// Add the animation layer to the video composition
let videoComposition = AVMutableVideoComposition(propertiesOf: composition)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
postProcessingAsVideoLayers: [videoLayer],
in: animationLayer
)
export.videoComposition = videoComposition
}
export.outputURL = exportURL
export.outputFileType = .mov
export.shouldOptimizeForNetworkUse = true
export.exportAsynchronously {
DispatchQueue.main.async {
switch export.status {
case .completed:
completionHandler(.success(exportURL))
default:
completionHandler(.failure(export.error ?? VideoEditorError.unknown))
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/785 ... foundation
Эффективное объединение нескольких видео в iOS: альтернативы AVFoundation ⇐ IOS
Программируем под IOS
1719389995
Anonymous
Какой наиболее эффективный способ объединить два или более видео в одно в приложении iOS? Я пробовал использовать AVFoundation, но он работает довольно медленно.
Я пробовал разные пресеты (даже AVAssetExportPreset1280x720), но процесс все равно очень медленный.
Есть ли какие-либо инфраструктуры или методы с ускорением на графическом процессоре, которые могут повысить производительность?
Вот моя текущая реализация.
func mergeVideos(
_ items: [VideoItem],
presetName: String,
overlay: Overlay?,
completionHandler: @escaping (Result) -> Void
) {
let fileName = "video-\(Date().description)"
let composition = AVMutableComposition()
let allItemsAreMuted = items.allSatisfy(\.isMuted)
guard
let compVideoTrack = composition.addMutableTrack(
withMediaType: .video,
preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)
)
else {
return completionHandler(.failure(VideoEditorError.unknown))
}
var compAudioTrack: AVMutableCompositionTrack?
if !allItemsAreMuted {
compAudioTrack = composition.addMutableTrack(
withMediaType: .audio,
preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)
)
if compAudioTrack == nil {
return completionHandler(.failure(VideoEditorError.unknown))
}
}
var currentTime = CMTime.zero
var loadedVideoTracks = [AVAsset: AVAssetTrack]()
var loadedAudioTracks = [AVAsset: AVAssetTrack]()
items.forEach { item in
do {
var audioTrack: AVAssetTrack?
let range = item.range ?? CMTimeRangeMake(start: CMTime.zero, duration: item.asset.duration)
var scaledDuration: CMTime?
if let rate = item.rate, rate != 1 {
scaledDuration = CMTime(seconds: range.duration.seconds / Double(rate), preferredTimescale: 1000)
}
if let videoTrack = loadedVideoTracks[item.asset] ?? item.asset.tracks(withMediaType: .video).first {
loadedVideoTracks[item.asset] = videoTrack
try compVideoTrack.insertTimeRange(range, of: videoTrack, at: currentTime)
}
if !item.isMuted {
audioTrack = loadedAudioTracks[item.asset] ?? item.asset.tracks(withMediaType: .audio).first
if let audioTrack = audioTrack {
loadedAudioTracks[item.asset] = audioTrack
try compAudioTrack?.insertTimeRange(range, of: audioTrack, at: currentTime)
}
}
if let scaledDuration = scaledDuration {
let currentRange = CMTimeRangeMake(start: currentTime, duration: range.duration)
compVideoTrack.scaleTimeRange(currentRange, toDuration: scaledDuration)
compAudioTrack?.scaleTimeRange(currentRange, toDuration: scaledDuration)
}
currentTime = CMTimeAdd(currentTime, scaledDuration ?? range.duration)
} catch {
completionHandler(.failure(error))
return
}
}
let exportURL = URL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent(fileName)
.appendingPathExtension("mov")
guard let export = AVAssetExportSession(
asset: composition,
presetName: presetName
) else {
completionHandler(.failure(VideoEditorError.unknown))
return
}
if let overlay = overlay {
let videoInfo = orientation(from: loadedVideoTracks.first!.value.preferredTransform)
let videoSize: CGSize
if videoInfo.isPortrait {
videoSize = CGSize(
width: loadedVideoTracks.first!.value.naturalSize.height,
height: loadedVideoTracks.first!.value.naturalSize.width
)
} else {
videoSize = loadedVideoTracks.first!.value.naturalSize
}
let overlayLayer = CALayer()
overlayLayer.contents = overlay.image.cgImage
overlayLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
overlayLayer.opacity = 1
overlayLayer.masksToBounds = true
overlayLayer.transform = CATransform3DMakeTranslation(overlay.rotationDegrees, 0, 0)
let radians = CGFloat(overlay.rotationDegrees) * .pi / 180.0
overlayLayer.transform = CATransform3DMakeRotation(radians, 1, 0, 0)
let videoLayer = CALayer()
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
let animationLayer = CALayer()
animationLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
animationLayer.addSublayer(videoLayer)
animationLayer.addSublayer(overlayLayer)
// Add the animation layer to the video composition
let videoComposition = AVMutableVideoComposition(propertiesOf: composition)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
postProcessingAsVideoLayers: [videoLayer],
in: animationLayer
)
export.videoComposition = videoComposition
}
export.outputURL = exportURL
export.outputFileType = .mov
export.shouldOptimizeForNetworkUse = true
export.exportAsynchronously {
DispatchQueue.main.async {
switch export.status {
case .completed:
completionHandler(.success(exportURL))
default:
completionHandler(.failure(export.error ?? VideoEditorError.unknown))
}
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/78551421/efficiently-merging-multiple-videos-in-ios-alternatives-to-avfoundation[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия