7

I'm generating an audio file programmatically, and I'd like to add metadata to it, such as the title and artist. I don't particularly care what format the file is written in, as long as AVPlayer will read it and send it to the playing device. (The whole goal is to send this generated audio and its track name to a Bluetooth device. I'm happy to explore easier ways to achieve this on iPhone that don't require writing the file or adding metadata directly to the file.)

So far I've discovered that AVAssetWriter will often just throw away metadata that it doesn't understand, without generating errors, so I'm stumbling a bit trying to find what combinations of file formats and keys are acceptable. So far I have not found a file format that I can auto-generate that AVAssetWriter will add any metadata to. For example:

let writer = try AVAssetWriter(outputURL: output, fileType: .aiff)  
let title = AVMutableMetadataItem()  
title.identifier = .commonIdentifierTitle  
title.dataType = kCMMetadataBaseDataType_UTF8 as String  
title.value = "The Title" as NSString  
writer.metadata = [title]  
// setup the input and write the file.  

I haven't found any combination of identifiers or fileTypes (that I can actually generate) that will include this metadata in the file.

My current approach is to create the file as an AIFF, and then use AVAssetExportSession to rewrite it as an m4a. Using that I've been able to add enough metadata that iTunes will show the title. However, Finder's "File Info" is not able to read the title (which it does for iTunes m4a files). My assumption is that if it doesn't even show up in File Info, it's not going to be sent over Bluetooth (I'll be testing that soon, but I don't have the piece of hardware I need handy).

Studying iTunes m4a files, I've found some tags that I cannot recreate with AVMetadataItem. For example, Sort Name (sonm). I don't know how to write tags that aren't one of the known identifiers (and I've tested all 263 AVMetadataIdentifiers).

With that background, my core questions:

  • What metadata tags are read by AVPlayer and sent to Bluetooth devices (i.e. AVRCP)?
  • Is it possible to write metadata directly with AVAssetWriter to a file format that supports Linear PCM (or some other easy-to-generate format)?
  • Given a known tag/value that does not match any of the AVMetadataIdentifiers), is it possible to write it in AVAssetExportSession?

I'll explore third-party id3 frameworks later, but I'd like to achieve it with AVFoundation (or other built-in framework) if possible.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • If I remember correctly, it has something to do with the format of `value`. I am not sure if you are not supposed to put `Data` there (utf8 encoded string). Also make sure to set `keySpace`. – Sulthan Mar 02 '18 at 15:54
  • One idea - is it possible that the AVRCP-borne title information is being sent via `MPNowPlayingInfoCenter`'s `nowPlayingInfo`? `AVPlayer` knowing so much about bluetooth profiles scares me a little. – Rhythmic Fistman Mar 02 '18 at 15:54
  • @Sulthan Thanks; yeah, I tried that. I don't think that's the issue since I can get it to store metadata in an m4a (via exporting) without converting to Data. – Rob Napier Mar 02 '18 at 17:26
  • 1
    @RhythmicFistman Via Twitter, I think you're really onto something here. It'll be my next exploration. Thanks again. https://twitter.com/cocoaphony/status/969610237761159168 – Rob Napier Mar 02 '18 at 17:27
  • hey @RobNapier what was the solution? :) – Pablo Martinez Jul 02 '18 at 17:45
  • @PabloMartinez Ultimately my use case was impossible. You have to grab the audio session briefly, which causes iTunes to drop for about a second, but causes non-iTunes players (like Spotify) to pause and never resume. This user experience was too poor and we had to give up the approach. (My goal was never to write this file; it was actually to set "Now Playing" information for bluetooth devices.) – Rob Napier Jul 02 '18 at 17:56

1 Answers1

1

I've been able to use AVAssetWriter to store metadata values in a .m4a file using the iTunes key space:

let songID = AVMutableMetadataItem()
songID.value = "songID" as NSString
songID.identifier = .iTunesMetadataSongID

let songName = AVMutableMetadataItem()
songName.value = "songName" as NSString
songName.identifier = .iTunesMetadataSongName

You can write compressed .m4a files directly using AVAssetWriter by specifying the correct settings when you set up the input object, so there’s no need to use an intermediate AIFF file.

Patrick Beard
  • 592
  • 6
  • 11