Audio Information of Current Track iOS Swift

Audio Information of Current Track iOS Swift

Here is example function to get audio Info:

import MediaPlayer

var url:NSURL!
let audioInfo = MPNowPlayingInfoCenter.defaultCenter()
var nowPlayingInfo:[NSObject:AnyObject] = [:]

func fetchMP3Info() {

let playerItem = AVPlayerItem(URL: url) //this will be your audio source
println(url.path!)

let metadataList = playerItem.asset.metadata as! [AVMetadataItem]
for item in metadataList {
if item.commonKey != nil && item.value != nil {
if item.commonKey == "title" {
println(item.stringValue)
nowPlayingInfo[MPMediaItemPropertyTitle] = item.stringValue
}
if item.commonKey == "type" {
println(item.stringValue)
nowPlayingInfo[MPMediaItemPropertyGenre] = item.stringValue
}
if item.commonKey == "albumName" {
println(item.stringValue)
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = item.stringValue
}
if item.commonKey == "artist" {
println(item.stringValue)
nowPlayingInfo[MPMediaItemPropertyArtist] = item.stringValue
}
if item.commonKey == "artwork" {
if let image = UIImage(data: item.value as! NSData) {
nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(image: image)
println(image.description)
}
}
}
}
audioInfo.nowPlayingInfo = nowPlayingInfo

}

Hope this will help.

Detecting which audio track is playing on device in iOS Swift

The short answer is no.

You may be able to retrieve song information from the iTunes library (if it's not a shared song using Home Sharing). Read about MPMusicPlayerController for more information. Specially the nowPlayingItem is probably what you're looking for.

However, most third-party applications such as Spotify, Deezer or Pandora will most likely have implemented their own player, which does not integrate with the iPod music player. This blog post also covers some of the details.

Get audio metadata from current playing audio in iTunes on OS X

Here's a simple example how to get the properties from the current track:

Tested on (El Capitan v10.11.5, iTunes 12.4 and Xcode 7.3).

import Cocoa
import ScriptingBridge
@objc protocol iTunesApplication {
optional func currentTrack()-> AnyObject
optional var properties: NSDictionary {get}
//if you need another object or method from the iTunes.h, you must add it here
}

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

func applicationDidFinishLaunching(aNotification: NSNotification) {
let iTunesApp: AnyObject = SBApplication(bundleIdentifier: "com.apple.iTunes")!
let trackDict = iTunesApp.currentTrack!().properties as Dictionary
if (trackDict["name"] != nil) {// if nil then no current track
print(trackDict["name"]!) // print the title
print(trackDict["artist"]!)
print(trackDict["album"]!)
print(trackDict["playedCount"]!)
// print(trackDict) // print the dictionary
}
}
}

How to get another app's currently playing audio

This isn't currently possible in iOS. Just changing your AVAudioSession category options to .MixWithOthers, what will be an option to get info Song Info from other apps, causes your nowPlayingInfo to be ignored.

iOS only considers non-mixing apps for inclusion in MPNowPlayingInfoCenter, because there is uncertainty as to which app would show up in (e.g.) Control Center if there are multiple mixing apps playing at the same time.

Proposal: An option would be to use a music fingerprinting algorithm to recognize what is being played by recording it from your App.

Some interesting projects in this direction:

Gracenote https://developer.gracenote.com/ Gracenote (which is owned by Sony) has opened up it's SDKs and APIs and has a proper dev portal.

EchoNest & Spotify API http://developer.echonest.com/ Fusioned with Spotify since March 2016

ACRCloud https://www.acrcloud.com/ offers ACR solutions for custom files such as TV commercials, music tec

Using Swift to display title of currently playing .MP3

you need to add the import statement for Media player and set the
General Media Item Property Keys
for nowPlayingInfo property. For the MPMediaItemPropertyArtwork you need to take a look at this MPMediaItemArtwork

import MediaPlayer

let audioInfo = MPNowPlayingInfoCenter.defaultCenter()
let audioName = audioPath.lastPathComponent!.stringByDeletingPathExtension
audioInfo.nowPlayingInfo = [ MPMediaItemPropertyTitle: audioName, MPMediaItemPropertyArtist:"artistName"]

To extract the metadata from your mp3 you need to create an AVPlayerItem and access its asset commonMetadata property

let playerItem = AVPlayerItem(URL: audioPath)
let metadataList = playerItem.asset.commonMetadata as! [AVMetadataItem]
for item in metadataList {
if item.commonKey == "title" {
println("Title = " + item.stringValue)
}
if item.commonKey == "artist" {
println("Artist = " + item.stringValue)
}
}

Note: You will have to invoke beginReceivingRemoteControlEvents() otherwise it will not work on the actual device.

override func viewDidLoad() {
super.viewDidLoad()
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
}

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

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.

Swift iOS, Play tracks sequentially from array using AVAudioPlayer, with some function in between each track?

The approach using audioPlayerDidFinishPlaying(_:,successfully:) is correct. In your code when you call playScript(c:) you will iterate through all audio files from conditions array and call startRecord method really quickly, while first audio is playing. All sounds will be placed in a queue and play one by one. I don't know contents of startRecord method, but I don't think that it was supposed to be called like that.

In order to avoid those problems you need to call playScript(c:) and then wait for method startRecord() to finish, and then call playScript(c:) again. So you can try something like this:

import AVFoundation

class SomeClass: NSObject, AVAudioPlayerDelegate {

var player: AVAudioPlayer?
var conditions = [String]()
var instructions: [() -> ()] = []

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
print("finished playing \(player.url)")
startRecord {
playNextInstruction()
}
}

func playScript(c: String)
{
let path = Bundle.main.path(forResource: c, ofType:"m4a")!
let url = URL(fileURLWithPath: path)

do {
self.player = try AVAudioPlayer(contentsOf: url)
self.player?.delegate = self
self.player?.play()
print(c)
print("playing script for " + c)
} catch {
print("couldn't load script")
}
}

func beginTest() {
instructions = conditions.shuffled().map { [unowned self] condition in
return {
self.playScript(c: condition)
}
}
playNextInstruction()
}

func playNextInstruction() {
if instructions.count != 0 {
instructions.remove(at: 0)()
} else {
exportData()
}
}

func exportData() {

}

func startRecord(completion: (() -> ())) {

}

}

If it won't work then I suggest to try searching problem somewhere else in your code.

How to track when song is finished AVAudioPlayer

I solved my problem with help of Leo Dabus.
I changed my edited code. I moved player?.delegate = self
to playSound func. Finally, it is working.

playSound & audioPlayerDidFinishPlaying function:

  func playSound(name: String ) {
guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else {
print("url not found")
return
}

do {
/// this codes for making this app ready to takeover the device audio
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)

/// change fileTypeHint according to the type of your audio file (you can omit this)
player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)

player?.delegate = self

// no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
player!.play()
} catch let error as NSError {
print("error: \(error.localizedDescription)")
}
}

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
print("finished")//It is working now! printed "finished"!
}

Do not forget to add AVAudioPlayerDelegate to ViewController!

class ViewController: UIViewController,AVAudioPlayerDelegate {

How to automatically go to the next track when the one is currently playing ends?

You should use AVAudioPlayer delegate method audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) which is called when the audio player finishes playing a sound.

  1. Make your PlayerViewController confirm to AVAudioPlayerDelegate protocol like this:

    class PlayerViewController: UIViewController, AVAudioPlayerDelegate {
  2. Make sure to set self as the delegate of the audioPlayer you create, to do that in your viewDidLoad,previousAction and nextTrack method you need to add

    audioPlayer.delegate = self

    after this line:

    audioPlayer = try AVAudioPlayer(contentsOfURL: mp3URL)
  3. Now you can use the delegate method to know when the audio is finished playing and go to the next track, just add this inside your class:

    func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
    if flag {
    self.nextTrack()
    } else {
    // did not finish successfully
    }
    }


Related Topics



Leave a reply



Submit