Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
665 views
in Technique[技术] by (71.8m points)

How to get Track Id from m4a audio file in swift 5.3

I am able to get some information from audio track but not track id. Anyone point me to how to get track id? I am using xcode 12.3. Thanks!

func getM4aAudioDetails(afile: URL) {

        let song = Song(context: moc)
        let avasset = AVAsset(url: afile as URL) as AVAsset
        let metadata = avasset.metadata(forFormat: AVMetadataFormat.iTunesMetadata)
        let cmetadata = avasset.commonMetadata

        let titleItems = AVMetadataItem.metadataItems(from: metadata, withKey: "?nam", keySpace: AVMetadataKeySpace(rawValue: "itsk"))
        if let data = titleItems.first, let title = data.stringValue {
            song.title = title
        }

        let artistItems = AVMetadataItem.metadataItems(from: metadata, withKey: "?ART", keySpace: AVMetadataKeySpace(rawValue: "itsk"))
        if let data = artistItems.first, let artist = data.stringValue {
            song.artist = artist
        }

        let albumItems = AVMetadataItem.metadataItems(from: metadata, withKey: "?alb", keySpace: AVMetadataKeySpace(rawValue: "itsk"))
        if let data = albumItems.first, let album = data.stringValue {
            song.album = album
        }

        let trackItems = AVMetadataItem.metadataItems(from: metadata, withKey: "trkn", keySpace: AVMetadataKeySpace(rawValue: "itsk"))
        if let data = trackItems.first, let trackString = data.stringValue {
            
            song.track = Int64(trackString)!
            print("Track: (song.track)")
        }

        let artworkItems = AVMetadataItem.metadataItems(from: cmetadata, filteredByIdentifier: .commonIdentifierArtwork)
        if let artworkItem = artworkItems.first {
            if let imageData = artworkItem.dataValue {
                //let image = NSImage(data: imageData)
                song.artwork = imageData as Data
                //print("image found")
            }
        }
        
        print("song title: (song.title)")
        print("song artist: (song.artist)")
        print("song name: (song.album)")
        print("song track: (song.track)")
    }

Prints: (excerpt)

  • song title: Loser

  • song artist: Beck

  • song name: Mellow Gold

  • song track: 0

  • song title: Jack-Ass

  • song artist: Beck

  • song name: Odelay

  • song track: 0


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You've already got the track number in trackItems. However it should be a dataValue, not a stringValue.

For one of my tracks I see 8 bytes of what looks like 4 16bit big endian integers:

0x00000008000e0000

Mine is track 8 of 14, so I guess you want the 2nd integer.

Here's more anecdotal evidence of the above:
https://lists.apple.com/archives/cocoa-dev/2009/Oct/msg00952.html

You could do what you want using this (note the symbols for the keySpace/keys):

if let trackItem = AVMetadataItem.metadataItems(from: metadata, filteredByIdentifier: .iTunesMetadataTrackNumber).first,
   let data = trackItem.dataValue,
   data.count == 8 {
    let bytes = [UInt8](data)
    let trackNumber = ((Int)(bytes[2]) << 8) | (Int)(bytes[3])
    let totalTracks = ((Int)(bytes[4]) << 8) | (Int)(bytes[5])
    print("trackNumber: (trackNumber)/(totalTracks)")
}

N.B.: it's different for mp3/ID3 in which case you'll want id3/TRCK & it's a stringValue containing an integer.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...