2012-05-23 7 views
16

Ich habe ein Problem mit AVAssetExportSession, wo der Fortschritt aufhört zu wachsen, aber der Status sagt immer noch, dass es exportiert. Dies ist eigentlich ein ziemlich seltenes Ereignis, es funktioniert fehlerfrei in 99,99% der Zeit, aber ich möchte das Problem trotzdem beheben.AVAssetExportSession stoppt den Fortschritt

So beginne ich den Export:

exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality]; 
    exportSession.videoComposition = videoComposition; 
    exportSession.outputFileType = @"com.apple.quicktime-movie"; 
    exportSession.outputURL = outputURL; 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 
     ... 
    }]; 

Dann einen Timer haben die Fortschritte überprüft:

AVAssetExportSessionStatus status = [exportSession status]; 
    float progress = 0; 
    if (status == AVAssetExportSessionStatusExporting) { 
     progress = [exportSession progress]; 
    } else if (status == AVAssetExportSessionStatusCompleted) { 
     progress = 1; 
    } 
    NSLog(@"%d %f", status, progress); 
    [delegate processor:self didProgress:progress]; 

Und die Ausgabe endet aussehen wie:

2012-05-23 14:28:59.494 **********[1899:707] 2 0.125991 
2012-05-23 14:28:59.994 **********[1899:707] 2 0.185280 
2012-05-23 14:29:00.494 **********[1899:707] 2 0.259393 
2012-05-23 14:29:00.994 **********[1899:707] 2 0.326093 
2012-05-23 14:29:01.494 **********[1899:707] 2 0.400206 
2012-05-23 14:29:01.995 **********[1899:707] 2 0.481729 
2012-05-23 14:29:02.495 **********[1899:707] 2 0.541019 
2012-05-23 14:29:02.997 **********[1899:707] 2 0.622542 
2012-05-23 14:29:03.493 **********[1899:707] 2 0.681832 
2012-05-23 14:29:03.995 **********[1899:707] 2 0.763355 
2012-05-23 14:29:04.494 **********[1899:707] 2 0.822645 
2012-05-23 14:29:04.994 **********[1899:707] 2 0.880082 
2012-05-23 14:29:05.493 **********[1899:707] 2 0.880082 
2012-05-23 14:29:05.994 **********[1899:707] 2 0.880082 
... 
2012-05-23 14:43:22.994 **********[1899:707] 2 0.880082 
2012-05-23 14:43:23.493 **********[1899:707] 2 0.880082 
2012-05-23 14:43:23.994 **********[1899:707] 2 0.880082 
2012-05-23 14:43:24.494 **********[1899:707] 2 0.880082 

(Hinweis: Es hört nicht immer bei dem gleichen Prozentsatz auf, es ist völlig zufällig)

Wie Sie von den Zeitstempeln sehen können, dauerte es 5 Sekunden, um die ersten 88% zu machen, und dann ließ ich es weitere 13 Minuten laufen (volle Videoverarbeitung dauert normalerweise nicht mehr als 10 Sekunden) Fortschritt.

Momentan ist meine einzige Option zu überprüfen, ob sich der Fortschritt in den letzten X Sekunden nicht geändert hat und dem Benutzer einfach mitzuteilen, dass es fehlgeschlagen ist, und es erneut zu versuchen.

Wer hat irgendwelche Ideen?

+0

Welche Art von Daten möchten Sie in die Exportsitzung schreiben? –

+0

Fügen Sie ein Video am Ende eines anderen hinzu und ersetzen Sie einen Teil des Audiomaterials durch einen anderen Teil einer Audiodatei. Verwenden der videoComposition zum Festlegen der bevorzugten Transformationen der Videos zu ihren Startzeiten. –

+0

Haben das gleiche Problem auch. Irgendwelche Fortschritte dabei? –

Antwort

3

Ich habe das gefunden!

Sie müssen richtig layerInstructions setzen:

AVMutableCompositionTrack *track = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 


AVMutableVideoCompositionLayerInstruction * layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:track]; 


AVMutableVideoCompositionInstruction * MainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
MainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, allTime); 
MainInstruction.layerInstructions = [NSArray arrayWithObject:layerInstruction]; 

Andernfalls es gerade stecken.

+0

Genau das war es für mich. Mein Export blieb bei 0,005 hängen (im Grunde nichts) und der Callback wurde nie ausgelöst. Vielen Dank! –

2

Ich frage mich, ob es ein Problem mit Threading ist - wenn der Timer und der Exporteur in verschiedenen Threads enden. (Der AVFoundation-Leitfaden sagt, dass der Exporteur nicht garantiert auf einem bestimmten Thread läuft.)

Haben Sie versucht, Schlüssel-Wert-Beobachtung statt eines Timers zu verwenden?

Barebones Beispiel:

// register for the notification 
[exportSession addObserver:someProcessor forKeyPath:@"progress" options:NSKeyValueObservingOptionNew context:NULL]; 

Dann in Ihrem Prozessor:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    // add some checks here 
    NSNumber *processNumber = [change objectForKey:NSKeyValueChangeNewKey]; 
    float process = [processNumber floatValue]; 
    [delegate processor:self didProgress:progress]; 
} 
+2

Dieser Ansatz sollte nicht verwendet werden, da in der Dokumentation angegeben wird, dass die "Fortschritts" -Eigenschaft nicht als Schlüsselwert beobachtbar ist. – aumanets

+0

@aumanets Hast du einen anderen Weg gefunden? –

+0

@PayalManiyar, es tut mir leid, es war lange her und ich kann mich nicht erinnern, wie ich dieses Problem verkauft habe. – aumanets

4

In meinem Fall dieses Problem aus mp4s stammte, die mit ungewöhnlichen Konfigurationen codiert wurden. Aber letztendlich verursacht ein Fehler in Apples Code das Problem.

Insbesondere arbeitete ich mit mp4s auf Facebook. Es scheint, dass wenn Facebook Videos codiert, es den ersten Frame der Videospur ablegt oder verschiebt. Untersuchen Sie das Video mit ffprobe zeigte:

 "r_frame_rate": "722/25", 
     "avg_frame_rate": "722/25", 
     "time_base": "1/28880", 
     "start_pts": 1000, 
     "start_time": "0.034626", 

0,034626 ist genau die Zeit für den Rahmen 2. Die Audiospur begann jedoch bei 0.

Leider Apples APIs berichten nicht richtig diese Startzeit für die Spur. Nachdem ich den AVAssetTrack vom AVAsset erhalten und seinen timeRange überprüft hatte, meldete er die Startzeit als 0. Es ist möglich, dass ich die Art des Track- und Assettimings falsch verstehe, aber das scheint ein Fehler zu sein.

Natürlich, beim Erstellen der Video-Komposition für die Export-Session habe ich den Track-Zeitbereich verwendet, der falsch war. Ich vermute, dass, wenn die Exportsitzung zum Zeitpunkt 0 nach Daten in der Spur sucht und nichts findet, sie verwirrt wird und dann, wie wir gesehen haben, einfach hängen bleibt und nicht einmal einen Fehler meldet - ein weiterer Fehler. Auch das Erstellen der Komposition mit videoCompositionWithPropertiesOfAsset: hilft nicht.

Ich habe noch nicht versucht, AVAssetReader und AVAssetWriter anstelle von AVAssetExportSession zu verwenden, also weiß ich nicht, ob Sie dort die gleiche Situation begegnen würden. Bis ich habe mehr Zeit zu erforschen, dass ich mit diesem Hack als Lösung kommen:

Setzen Sie den Zeitbereich für die Spur Einsetzen und Video-Anleitungen verwendet, um bei 1 oder 2 Frames zu beginnen in:

CMTimeRange videoTimeRange = videoTrack.timeRange; 
videoTimeRange.start = CMTimeMake(1, ceil(videoTrack.nominalFrameRate)); 

Offensichtlich gilt dieser Hack nur für die spezielle Situation, in der die Startzeit der Videospur nicht 0 ist. Ich vermute, dass dieser Fehler im Allgemeinen von ungewöhnlichen Mediencodierungen herrührt, die AVAssetExportSession und die zugehörigen Klassen nicht erwarten.

+0

Haben Sie jemals eine bessere Lösung dafür gefunden? Ich habe das versucht, aber ich bin mir nicht sicher, wo Sie die Startposition ändern wollten. Wenn ich meine Assets zum Track hinzufüge, verwende ich '[track insertTimeRange: CMTimeRangeMake (kCMTimeZero, asset.duration) ... asset.] 'Wenn Sie versuchen, Ihre CMTimeRange-Methode zu verwenden, funktioniert es nicht. Eigentlich wird es noch schlimmer, da ich später aus irgendeinem Grund die natürliche Größe der Tracks nicht abrufen kann. Aber ich könnte den Rahmen an die falsche Stelle setzen? Wie auch immer, eine richtige Lösung für diesen Fehler wäre viel besser. – Sti

+0

Meine Arbeit daran hat aufgehört, bevor ich eine bessere Lösung gefunden habe. Es gibt keine Garantie, dass dies in Ihrem Fall funktioniert, und im Allgemeinen gibt es viele Fallstricke bei der Arbeit mit AVFoundation. Sie würden jedoch die obigen Zeilen verwenden, um einen angepassten Bereich zu erstellen, der für das Einfügen von Spuren verwendet werden kann. Zum Beispiel: '[track insertTimeRange: adjustedVideoTimeRange ofTrack: videoTrack atTime: kCMTimeZero Fehler: & error]' – kball

+0

Wie ich geschrieben habe, habe ich das ohne Glück versucht. Es passiert immer noch. Das Seltsame ist, dass alle Video-Dateien, die ich benutze, in der App selbst mit AVAssetWriter erstellt werden. Ich bin mir nicht sicher, ob ich das gleiche Problem habe. Ich versuche nun, ffprobe auf einer der fehlgeschlagenen Dateien zu verwenden, aber ich weiß nicht, wie ich es verwenden soll. Beim Ausführen (auf osx/terminal) './ffprobe test.mp4' sehe ich nur einige der Metadaten über die Datei. Die Dokumentation ist seltsam komisch, gibt es eine Option, die ich verwenden sollte, um Ihr Ergebnis zu bekommen? – Sti