如何在iOS10(Swift 3)中获取现在播放歌曲的歌词

dan*_*hed 5 avfoundation mpmediaitem ios swift swift3

我想显示当前由iOS系统播放器播放的歌曲中的歌词.

这是我的自定义播放器:

import UIKit
import MediaPlayer
import AVFoundation

class NowPlayingController: NSObject {
    var musicPlayer: MPMusicPlayerController {
        if musicPlayer_Lazy == nil {
            musicPlayer_Lazy = MPMusicPlayerController.systemMusicPlayer()

            let center = NotificationCenter.default
            center.addObserver(self,
                selector: #selector(self.playingItemDidChange),
                name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange,
                object: musicPlayer_Lazy)
            musicPlayer_Lazy!.beginGeneratingPlaybackNotifications()
        }

        return musicPlayer_Lazy!
    }
    private var musicPlayer_Lazy: MPMusicPlayerController?

    var nowPlaying: MPMediaItem?

    //If song changes
    func playingItemDidChange(notification: NSNotification) {
        nowPlaying = musicPlayer.nowPlayingItem
    }
}
Run Code Online (Sandbox Code Playgroud)

为了获得nowPlaying项目的歌词,我尝试了两种方法,并且它们都会返回nil.

此代码始终返回nil:

let lyricsText = nowPlaying?.value(forProperty: MPMediaItemPropertyLyrics) as? NSString as String?
Run Code Online (Sandbox Code Playgroud)

在以下代码中MPMediaItemPropertyAssetURL始终返回nil而不是实际的URL:

let songUrl = nowPlaying?.value(forProperty: MPMediaItemPropertyAssetURL) as? NSURL as URL?
if songUrl != nil {
    let songAsset = AVURLAsset(url: songUrl!, options: nil)
    lyricsText = songAsset.lyrics
Run Code Online (Sandbox Code Playgroud)

所有歌曲都在设备上(由iTunes同步),包含歌词(显示在系统播放器中)和非DRM保护(翻录aac/mp3).

我正在真实设备上测试它:iPhone 6s/iOS 10.3

任何建议我如何获得歌词或为什么MPMediaItemPropertyAssetURL返回nil?

dan*_*hed 3

我不知道为什么它不起作用,但看起来相同的代码现在可以正常工作。也许它以某种方式连接到我现在用于播放器实例的单例。这是 100% 工作的 Swift 3 版本:

import UIKit
import MediaPlayer
import AVFoundation

class NowPlayingController: NSObject {

    static let sharedController = NowPlayingController()

    //MARK: Init
    private override init () {
        super.init()

        var musicPlayer_Lazy: MPMusicPlayerController?

        // System player instance
        if musicPlayer_Lazy == nil {
            musicPlayer_Lazy = MPMusicPlayerController.systemMusicPlayer()
            NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.playingItemDidChange),
                                               name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange,
                                               object: musicPlayer_Lazy)
            musicPlayer_Lazy!.beginGeneratingPlaybackNotifications()
        }

        self.musicPlayer = musicPlayer_Lazy!
    }

    // MARK: Class properties
    var musicPlayer: MPMusicPlayerController!
    var nowPlaying: MPMediaItem?

    // MARK: Methods
    func playingItemDidChange(notification: NSNotification) {
        nowPlaying = musicPlayer.nowPlayingItem
        NotificationCenter.default.post(newSongNotification as Notification)
    }

    func getLyrics() {
        let songUrl = nowPlaying?.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
        let songAsset = AVURLAsset(url: songUrl!, options: nil)
        let lyricsText = songAsset.lyrics
    }
}
Run Code Online (Sandbox Code Playgroud)