TLDR - vedi EDITfissaggio orientamento quando la cucitura (la fusione) video utilizzando AVMutableComposition
sto creando un applicazione di test a Swift dove voglio ricamare più video insieme dal mio directory apps documenti utilizzando AVMutableComposition
.
Ho avuto successo nel fare questo in una certa misura, tutti i miei video sono cuciti insieme e tutto sta mostrando la dimensione corretta ritratto e paesaggio.
Il mio problema è, tuttavia, che tutti i video vengono visualizzati nell'orientamento dell'ultimo video nella compilation.
So che per risolvere questo problema dovrò aggiungere istruzioni di livello per ogni traccia che aggiungo, tuttavia non riesco a farlo bene, con le risposte che ho trovato l'intera compilation sembra uscire in un ritratto l'orientamento con i video panoramici è semplicemente ridimensionato per adattarsi alla visualizzazione verticale, quindi quando accendo il telefono su un lato per visualizzare i video panoramici sono ancora piccoli poiché sono stati adattati alle dimensioni di un ritratto.
Questo non è il risultato che sto cercando, voglio la funzionalità cioè atteso se un video è il paesaggio si mostra in scala quando in modalità verticale, ma se il telefono viene ruotato voglio che il video del paesaggio per riempire lo schermo (come è quando visualizzeresti semplicemente un video di paesaggio nelle foto) e lo stesso per il ritratto in modo che quando viene visualizzato in verticale sia a schermo intero e quando viene ruotato di lato il video viene ridimensionato in dimensioni orizzontali (come quando guarda un ritratto in foto).
In sintesi il risultato desiderato che voglio è che durante la visualizzazione di una compilation che ha paesaggio e ritratto video posso visualizzare l'intera compilation con il mio telefono su un lato e il video paesaggio sono a schermo intero e ritratto viene ridimensionato, o durante la visualizzazione lo stesso video in verticale, i video ritratti sono a schermo intero e i video panoramici vengono ridimensionati.
Con tutte le risposte ho trovato che questo non era il caso e sembravano tutti avere un comportamento molto inaspettato quando si importava un video dalle foto da aggiungere alla compilazione e lo stesso comportamento casuale quando si aggiungevano i video che erano stati girati con la parte anteriore fotocamera frontale (per essere chiari con i miei attuali video di implementazione importati dalla libreria e i video "selfie" appaiono nella dimensione corretta senza questi problemi).
Sto cercando un modo per ruotare/scalare questi video in modo che siano sempre visualizzati con l'orientamento corretto e la scala in base a quale direzione l'utente sta tenendo il telefono.
EDIT: Ora so che non è possibile avere entrambi gli orientamenti orizzontale e verticale in un singolo video, quindi il risultato atteso che sto cercando sarebbe quello di avere il video finale in orientamento orizzontale. ho capito come fare a cambiare tutti gli orientamenti e le scale per ottenere tutto allo stesso modo, ma il mio output è un video di ritratto se qualcuno potesse aiutarmi a cambiare questo modo che il mio output sia orizzontale sarebbe apprezzato.
Qui di seguito è la mia funzione per ottenere le istruzioni per ogni video:
func videoTransformForTrack(asset: AVAsset) -> CGAffineTransform
{
var return_value:CGAffineTransform?
let assetTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
let transform = assetTrack.preferredTransform
let assetInfo = orientationFromTransform(transform)
var scaleToFitRatio = UIScreen.mainScreen().bounds.width/assetTrack.naturalSize.width
if assetInfo.isPortrait
{
scaleToFitRatio = UIScreen.mainScreen().bounds.width/assetTrack.naturalSize.height
let scaleFactor = CGAffineTransformMakeScale(scaleToFitRatio, scaleToFitRatio)
return_value = CGAffineTransformConcat(assetTrack.preferredTransform, scaleFactor)
}
else
{
let scaleFactor = CGAffineTransformMakeScale(scaleToFitRatio, scaleToFitRatio)
var concat = CGAffineTransformConcat(CGAffineTransformConcat(assetTrack.preferredTransform, scaleFactor), CGAffineTransformMakeTranslation(0, UIScreen.mainScreen().bounds.width/2))
if assetInfo.orientation == .Down
{
let fixUpsideDown = CGAffineTransformMakeRotation(CGFloat(M_PI))
let windowBounds = UIScreen.mainScreen().bounds
let yFix = assetTrack.naturalSize.height + windowBounds.height
let centerFix = CGAffineTransformMakeTranslation(assetTrack.naturalSize.width, yFix)
concat = CGAffineTransformConcat(CGAffineTransformConcat(fixUpsideDown, centerFix), scaleFactor)
}
return_value = concat
}
return return_value!
}
E l'esportatore:
// Create AVMutableComposition to contain all AVMutableComposition tracks
let mix_composition = AVMutableComposition()
var total_time = kCMTimeZero
// Loop over videos and create tracks, keep incrementing total duration
let video_track = mix_composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
var instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: video_track)
for video in videos
{
let shortened_duration = CMTimeSubtract(video.duration, CMTimeMake(1,10));
let videoAssetTrack = video.tracksWithMediaType(AVMediaTypeVideo)[0]
do
{
try video_track.insertTimeRange(CMTimeRangeMake(kCMTimeZero, shortened_duration),
ofTrack: videoAssetTrack ,
atTime: total_time)
video_track.preferredTransform = videoAssetTrack.preferredTransform
}
catch _
{
}
instruction.setTransform(videoTransformForTrack(video), atTime: total_time)
// Add video duration to total time
total_time = CMTimeAdd(total_time, shortened_duration)
}
// Create main instrcution for video composition
let main_instruction = AVMutableVideoCompositionInstruction()
main_instruction.timeRange = CMTimeRangeMake(kCMTimeZero, total_time)
main_instruction.layerInstructions = [instruction]
main_composition.instructions = [main_instruction]
main_composition.frameDuration = CMTimeMake(1, 30)
main_composition.renderSize = CGSize(width: UIScreen.mainScreen().bounds.width, height: UIScreen.mainScreen().bounds.height)
let exporter = AVAssetExportSession(asset: mix_composition, presetName: AVAssetExportPreset640x480)
exporter!.outputURL = final_url
exporter!.outputFileType = AVFileTypeMPEG4
exporter!.shouldOptimizeForNetworkUse = true
exporter!.videoComposition = main_composition
// 6 - Perform the Export
exporter!.exportAsynchronouslyWithCompletionHandler()
{
// Assign return values based on success of export
dispatch_async(dispatch_get_main_queue(), {() -> Void in
self.exportDidFinish(exporter!)
})
}
Ci scusiamo per la lunga spiegazione Volevo solo assicurarsi che ero molto chiaro con quello che stavo chiedendo perché altre risposte non hanno funzionato per me.
per quanto riguarda la modifica ho detto che aveva fatto registrare una taglia per far sapere a qualcuno lo farò assegnare punti per una risposta corretta, anche se non di taglie è stato pubblicato ancora IE entro i primi 2 giorni. ora ho aggiunto una taglia e ancora guadagnato attenzione zero su questa domanda tranne che per le modifiche ???? – AngryDuck
Per una domanda con una dipendenza da dati esterni come questo, sarebbe utile se si potesse pubblicare l'intero progetto, inclusi i video di esempio, quindi è facile da riprodurre. – jtbandes
Questo è un campione minimo completo che mostrerà il problema hai solo bisogno di 2 video come AVAssets nell'array video uno su orizzontale e uno in verticale e vedrai il problema – AngryDuck