4
votes

We have a video player where we play videos inside an AVPlayer (1GB of content in about 8MB .mov files in size). We load the AVPlayer using an AVMutableComposition of a video track and audio track that are on local disk bundled with the app.

We do something like:

AVAsset* videoAsset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];
AVAsset* voiceAsset = useVoice ? [[AVURLAsset alloc] initWithURL:voiceUrl options:nil] : nil;

AVMutableComposition* composition = [[AVMutableComposition alloc] init];

AVMutableCompositionTrack* videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack* audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack* voiceTrack = useVoice ? [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid] : nil;

NSError* error = nil;
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject] atTime:kCMTimeZero error:&error];
if (error) {
    [[MNGAppDelegate sharedManagers].errorManager presentError:error];
}

if ([videoAsset tracksWithMediaType:AVMediaTypeAudio].count > 0) {
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] firstObject] atTime:kCMTimeZero error:&error];
    if (error) {
        [[MNGAppDelegate sharedManagers].errorManager presentError:error];
    }
}

if (useVoice) {
    [voiceTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, voiceAsset.duration) ofTrack:[[voiceAsset tracksWithMediaType:AVMediaTypeAudio] firstObject] atTime:kCMTimeZero error:&error];
    if (error) {
        [[MNGAppDelegate sharedManagers].errorManager presentError:error];
    }
}

And we load it using a replaceCurrentItemWithPlayerItem (except for the first one).

    [self.player replaceCurrentItemWithPlayerItem:nextItem];

We never create a playlist or can go back. We simply replace it when a new video needs to be played.

What we're noticing is that VM Tracker is showing our Dirty Size is going crazy. Once we play the first 8MB file we approach about 80MB of dirty. As we replace more and more videos we can easily get our Dirty Size to 200MB+. Within about 20-30 videos the app will usually be killed and we get a Low Memory Crash Log.

Is there something special we should be doing to reduce the memory of AVPlayer as we replace clips in the player?

2
Hello, I have similar problem - playing video make app memory usage growing up with each new item... Do you find a solution, mean how to free or reduce memory usage after playing items? - hbk

2 Answers

0
votes

I have found that setting:

    [someAssetWriterInput setExpectsMediaDataInRealTime:NO];

.. has some effect on memory pressure experienced during AVComposition-oriented export sessions .. it would appear to be at least one way to govern the internal memory usage within the framework ..

0
votes
        self.player?,pause()
        self.activityIndicator?.startAnimating()
        self.removeObserverPlayerItem()
        let item = AVPlayerItem(url: fileurl)
        player?.replaceCurrentItem(with: item)
        self.addObserverPlayerItem()
        self.player?.play()

This will controll your memory and will take only needed memory. this resolved my problem.