AVFragmentedAssetMinder not working?

I am running on a MacBook with macOS Catalina 10.15.6 & Xcode 11.6
I am capturing video & audio from the built-in camera and writing them to a QuickTime movie file on disk using an AVAssetWriter created like this:

Code Block
self.myVideoWriter = [[AVAssetWriter alloc] initWithURL: targetURL fileType: self.myCaptureFileType error: &err];
self.myVideoWriter.movieFragmentInterval = CMTimeMake( 5, 1 );

The movie file is written ok and I can open and playback the resulting .mov file with other video apps during the capture.

The problem is I cannot get any AVAssetDurationDidChangeNotifications in my program.

After the AVAssetWriter starts writing to disk, I create an AVFragmentedAsset for the targetURL above and I create an AVFragmentedAssetMinder for the asset like this:

Code Block
AVFragmentedAsset *theAsset = [[AVFragmentedAsset alloc] initWithURL: targetURL options: @{ AVURLAssetPreferPreciseDurationAndTimingKey : @(YES) }];
self.fragmentedAssetMinder = [[AVFragmentedAssetMinder alloc] initWithAsset: theAsset mindingInterval: 5];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(durationChanged:) name: AVAssetDurationDidChangeNotification object: nil];


The problem is that the durationChanged: notification handler is never called.

Any ideas what am I doing wrong?

Accepted Reply

After a second reading of your reply, I moved the AVFragmentMinder creation after the asset duration is loaded. Now the AVAssetDurationDidChangeNotification is properly logged in my problem.

Thank you.

Replies

One thing to try: Make sure you load the initial duration on your fragmented asset, preferably using -loadValuesAsynchronouslyForKey: or by directly querying the "duration" property (but avoid doing this on the main thread as it can block). That ought to allow AVFragmentedAssetMinder to notice that the duration has changed.
I am doing this. After creating the fragmentedAsset I call:


Code Block
- (void) loadTheAsset: (AVAsset *) anAsset
{
NSArray *assetKeysToLoadAndTest = @[ @"playable", @"hasProtectedContent", @"tracks", @"duration", @"canContainFragments", @"containsFragments" ];
[anAsset loadValuesAsynchronouslyForKeys: assetKeysToLoadAndTest completionHandler: ^(void) {
dispatch_async(dispatch_get_main_queue(), ^(void) {
NSLog(@"           playable: %@", (anAsset.playable ? @"YES" : @"NO"));
NSLog(@"           duration: %.2lf", CMTimeGetSeconds(anAsset.duration));
NSLog(@"canContainFragments: %@", (anAsset.canContainFragments ? @"YES" : @"NO"));
NSLog(@"  containsFragments: %@", (anAsset.containsFragments ? @"YES" : @"NO"));
});
}];
}


All properties have their expected values.

After a second reading of your reply, I moved the AVFragmentMinder creation after the asset duration is loaded. Now the AVAssetDurationDidChangeNotification is properly logged in my problem.

Thank you.