Add metadata to .mov

I tried to translate the code of AVTimedAnnotationWriter from Objective-C to Swfit. Everything works but when I'm writing the metadata part, it fails.

I noticed that when the mediaType = "meta" (line13). It will occur one more copyNextTimedMetadataGroup(). Any idea?

func startReadingAndWritingWithCompletionHandler(localCompletionHandler: dispatch_block_t) {
        self.completionHandler = localCompletionHandler
  
        assetWriterInput?.requestMediaDataWhenReadyOnQueue(serializationQueue!, usingBlock: { () -> Void in
            if(self.finished!) {
                return
            }
            var completedOrFailed: Bool = false
            /
            while ((self.assetWriterInput?.readyForMoreMediaData)! && !completedOrFailed) {
                var sampleBuffer: CMSampleBufferRef? = nil
                var metadataGroup: AVTimedMetadataGroup? = nil
                if((self.assetWriterInput?.mediaType)! == "meta") {
                    metadataGroup = self.metadataSampleProvider?.copyNextTimedMetadataGroup()
                }
                else {
                    sampleBuffer = self.sampleProvider!.copyNextSampleBuffer()
                }
          
                if (sampleBuffer != nil) {
                    let success: Bool = (self.assetWriterInput?.appendSampleBuffer(sampleBuffer!))!
                    sampleBuffer = nil
                }
                else if (metadataGroup != nil) {
                    let success: Bool = (self.assetWriterAdaptor?.appendTimedMetadataGroup(metadataGroup!))!
                    completedOrFailed = !success
                }
                else {
                    completedOrFailed = true
                }
          
            }
      
            if(completedOrFailed) {
                self.callCompletionHandlerIfNecessary()
            }
      
        })
    }

My AVTimedMetadataGroup count is exactly 181. But the copyNextTimedMetadataGroup() will run 182 times. In other words, the last try will return nil. (Error)

func copyNextTimedMetadataGroup() -> AVTimedMetadataGroup {
        var group: AVTimedMetadataGroup?
        // self.currentSampleNum = 0 ; self.numOfSamples = 181
        if (self.currentSampleNum < self.numOfSamples)
        {
            group = self.metadataSamples[currentSampleNum] as! AVTimedMetadataGroup
            self.currentSampleNum++
        }
        return group!
    }

It runs one more time because that's when completedOrFailed is set to true because of completion.

The fix is simple:


func copyNextTimedMetadataGroup() -> AVTimedMetadataGroup? {
var group: AVTimedMetadataGroup?
if (self.currentSampleNum < self.numOfSamples) 
{
group = self.metadataSamples[currentSampleNum] as! AVTimedMetadataGroup
self.currentSampleNum++
}
return group
}


BTW you can make your code a little more compact, like so:


var completedOrFailed = false           // Bool type is inferred
var sampleBuffer: CMSampleBufferRef?      // nil is default value


Jan E

Thanks. It works.

However, I tried to get metadata out from my exported file, I got an empty metadata. why?


func playVideo(url: NSURL)
{
     let asset = AVURLAsset(URL: url)
     print(asset.metadata)
}


[] // My console line print out no metadata

asset.metadata are the "global" metadata. You are creating a timed metadata track.

Try printing asset.tracks


Jan E.

I am out of ideas.

You can copy the metadata with


writer.metadata = sourceAsset.metadata


I ran the AVTimedAnnotationWriter project on my iPad and it worked OK.

I would like to save the movie to the Photos album instead of the temporary directory. Can you tell how to do that?


Jan E.

Try this

// The temporary path for the video before saving it to the photo album
self.destinationAssetURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), @"Movie.MOV"]];

That is the code for saving to the temporary folder.

I want to replace that by the photos directory or whatever it is called on iOS (I am a Mac programmer).


Jan E.

You can use UISaveVideoAtPathToSavedVideosAlbum to save the video to the Camera Roll album (devices with camera) or Saved Photos album (devices without camera).

Add metadata to .mov
 
 
Q