2012-05-23 8 views
16

Mam problem z AVAssetExportSession, w której postępy przestają się zwiększać, ale stan nadal mówi, że eksportuje. Jest to dość rzadkie zdarzenie, działa bezbłędnie w 99,99% czasu, ale i tak chcę rozwiązać problem.AVAssetExportSession przestaje się rozwijać

Więc zacznę eksportującego:

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

wtedy timer kontroli postępu prac:

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]; 

a wyjście kończy się patrząc jak:

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 

(uwaga: Nie zatrzymuje się przy tym samym procencie za każdym razem, jest całkowicie losowy)

Jak widać na podstawie znaczników czasu, wykonanie pierwszych 88% zajęło 5 sekund, a następnie pozwoliłem mu działać przez kolejne 13 minut (pełne przetwarzanie wideo zwykle zajmuje nie więcej niż 10 sekund) bez żadnych zmian postęp.

Obecnie moją jedyną opcją jest sprawdzenie, czy postęp nie zmienił się w ciągu ostatnich X sekund i po prostu powiedzieć użytkownikowi, że się nie udało i spróbować ponownie.

Ktoś ma jakieś pomysły?

+0

jakiego rodzaju dane próbujesz zapisać w sesji eksportu, może być przydatne poznanie –

+0

Dodawanie wideo na końcu innego i zastępowanie części audio inną częścią pliku audio. Korzystanie z wideoComposition do ustawiania preferowanych transformacji filmów w ich godzinach rozpoczęcia. –

+0

Mając również ten sam problem. jakiekolwiek postępy w tej sprawie? –

Odpowiedz

3

Znalazłem to!

Musisz ustawić poprawne layerInstructions:

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]; 

W przeciwnym razie po prostu zakleszczony.

+0

To jest dokładnie to, co było dla mnie. Mój eksport utknął na poziomie 0,005 (w zasadzie nic), a callback nigdy nie odpalił. Dzięki! –

2

Zastanawiam się, czy to problem z wątkami - jeśli licznik czasu i eksporter znajdą się w różnych wątkach. (Przewodnik AVFoundation mówi, że eksporter nie może działać na żadnym konkretnym wątku).

Czy próbowałeś używać obserwowania wartości klucz-wartość zamiast licznika czasu?

Barebone przykład:

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

Następnie w edytorze:

- (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

Tego podejścia nie należy używać, ponieważ w dokumentacji podano, że właściwość "postęp" nie jest widoczna jako klucz-wartość. – aumanets

+0

@aumets można znaleźć w inny sposób? –

+0

@PayalManiyar, przykro to było dawno temu i naprawdę nie pamiętam, jak sprzedałem ten problem. – aumanets

4

W moim przypadku problem ten wynika z MP4s które zostały zakodowane z nietypowych konfiguracjach. Ale ostatecznie błąd w kodzie Apple powoduje problem.

W szczególności pracowałem z mp4 na Facebooku. Wygląda na to, że gdy Facebook zakoduje filmy, spada lub przesuwa pierwszą klatkę na ścieżce wideo. Badając wideo z ffprobe pokazał:

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

0,034626 jest właśnie czas na ramie 2. ścieżki dźwiękowej, jednak zaczęło się od 0.

API Niestety Apple nie prawidłowo zgłosić ten czas rozpoczęcia tor. Po pobraniu zestawu AVAssetTrack z zestawu AVA i sprawdzeniu jego timeRange raportowano czas rozpoczęcia jako 0. Możliwe jest, że nie rozumiem natury czasu i czasu zasobów, ale wydaje się, że to błąd.

Oczywiście przy tworzeniu kompozycji wideo do sesji eksportu użyłem przedziału czasowego ścieżki, który był nieprawidłowy. Podejrzewam, że gdy sesja eksportu wyszuka dane na ścieżce w czasie 0 i nic nie znajdzie, zostanie zmylona, ​​a potem, jak widzieliśmy, po prostu zawiesza się i nawet nie zgłasza błędu - kolejny błąd. Nawet tworzenie kompozycji za pomocą właściwości videoCompositionWithPropertiesOfAsset: nie pomaga.

Nie próbowałem jeszcze użyć AVAssetReader i AVAssetWriter zamiast AVAssetExportSession, więc nie wiem, czy spotkałaby się tam taka sama sytuacja. Dopóki mam więcej czasu na zwiedzanie, że trafiłeś na ten siekać jako rozwiązanie:

zresetować zakres czasowy używany instrukcje wstawiania utwór i video rozpocząć się 1 lub 2 klatek:

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

Oczywiście ten hack odnosi się tylko do konkretnej sytuacji, w której czas rozpoczęcia ścieżki wideo nie wynosi 0. Przypuszczam, że ten błąd generalnie wynika z nietypowych kodowań mediów, których AVAssetExportSession i powiązanych z nim klas się nie spodziewano.

+0

Czy kiedykolwiek znalazłeś lepsze rozwiązanie? Próbowałem to zrobić, ale nie jestem pewien, gdzie chciałeś zmienić początkową pozycję. Dodając moje zasoby do utworu, używam '[track insertTimeRange: CMTimeRangeMake (kCMTimeZero, asset.duration) ... asset ..] 'Podczas próby użycia metody CMTimeRange, to nie działa. W rzeczywistości jest gorzej, bo z jakiegoś powodu nie mogę odzyskać naturalnej wielkości torów. Ale mógłbym umieścić ramkę w niewłaściwym miejscu? W każdym razie właściwe rozwiązanie tego błędu byłoby o wiele lepsze. – Sti

+0

Moja praca nad tym zatrzymała się zanim znalazłem lepsze rozwiązanie. Nie ma gwarancji, że to zadziała w twoim przypadku, a generalnie istnieje wiele pułapek podczas pracy z AVFoundation. Ale możesz użyć powyższych linii, aby utworzyć dostosowany zakres do wstawienia ścieżki. Na przykład: '[track insertTimeRange: adjustedVideoTimeRange ofTrack: videoTrack atTime: błąd kCMTimeZero: & error]' – kball

+0

Jak napisałem, próbowałem tego bez powodzenia. Nadal się dzieje. Dziwne jest to, że wszystkie pliki wideo, których używam, są tworzone w samej aplikacji przy użyciu AVAssetWriter. Nie jestem pewien, czy doświadczam tego samego problemu. Próbuję teraz użyć/uruchomić ffprobe na jednym z uszkodzonych plików, ale nie wiem jak z niego korzystać. Podczas uruchamiania (na osx/terminal) './ffprobe test.mp4' widzę tylko niektóre metadane dotyczące pliku. Dokumentacja jest dziwnie dziwna, czy jest opcja, której powinienem użyć, aby uzyskać twój wynik? – Sti