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

5

我希望能够显示当前正在播放的 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
    }
}

nowPlaying 项目获取歌词,我尝试了两种方法,但都 始终 返回 nil
这段代码始终返回 nil:
let lyricsText = nowPlaying?.value(forProperty: MPMediaItemPropertyLyrics) as? NSString as String?

在以下代码中,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

所有歌曲均存储在设备上(通过iTunes同步),包含歌词(在系统播放器中显示)且没有受到DRM保护(使用aac/mp3格式进行了转换)。

我正在真实设备iPhone 6s/iOS 10.3上进行测试。

有什么建议可以让我获取歌词或者解决MPMediaItemPropertyAssetURL返回nil的问题吗?


现在,大多数iTunes内容都受到FairPlay DRM的保护,或者是Apple Music(也受到FairPlay保护?不确定)。这种类型的内容总是返回nil的MPMediaItemPropertyAssetURL。你只能以“自动唱机”的方式使用它,让iOS为你播放音乐。更复杂的用例是不可能的。 - Rhythmic Fistman
你尝试过像下面这样访问吗?let lyric = nowPlaying?.lyrics let assetUrl = nowPlaying?.assetURL还请注意。 - Bluewings
@RhythmicFistman 这不是问题,因为我的内容不是iTunes Store的内容。但我已经使用以下方法进行了双重检查,它返回“false”(表示歌曲上没有DRM):nowPlaying?.hasProtectedAsset - dandepeched
@Bluewings 我刚尝试了一下,两个都返回 nil - dandepeched
2个回答

2

我不知道为什么它之前不能正常工作,但是现在看起来相同的代码可以正常工作了。可能与我现在用于玩家实例的单例有关。这是完全可行的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
    }
}

NotificationCenter.default.post(newSongNotification as Notification)造成了一个错误,nowPlaying始终返回nil。为什么?@dandepeched - Davender Verma
1
@dandepected 仍然返回 nil。我正在使用上述代码。NowPlayingController.sharedController.getLyrics() - Davender Verma
1
歌词总是空的,你能帮我吗? - Yogesh Patel

1
我知道这有点老了,但我刚刚花了大约4个小时研究如何从MP3文件中读取歌词,如果它有歌词的话。我正在使用AVAudioPlayer而不是MPMusicPlayerController。天啊,这太简单了... 适用于macOS的Swift 5.3 (我不知道这是否适用于iOS,但我想应该可以)
import AVFoundation

func getLyrics(url: URL) -> String? {
    let asset = AVAsset(url: url)
    return asset.lyrics
}

请注意它返回一个可选项,所以最好检查是否为nil。希望这能为某人节省数小时的研究时间。
请参阅苹果文档此处

谢谢提供的信息。然而,我在我的iOS音乐播放器中尝试了很多首歌曲,每一首歌的歌词属性都是空的。 :-( - Carl Smith
我不开发iOS,但我觉得奇怪的是,如果歌词嵌入到你的mp3文件(或其他媒体类型)中,这对你来说不起作用。答案中链接的开发者文档显示,此方法适用于所有iOS版本,包括4.0及以后的版本。 - SouthernYankee65
最大的问题是歌词是否嵌入到了MP3文件中。我唯一的猜测是它不起作用的原因可能是它们没有被嵌入。我也觉得这很奇怪(和悲哀)。但我很感激这些信息! - Carl Smith
如果它们不存在,那么返回值将为nil,这是有意义的。为了测试它,将mp3导入到Music中并添加一些歌词,然后更改文件url以指向Music存储它的位置,或将其同步到iOS设备并进行测试,或者使用你知道有歌词的文件进行测试。这只是一个想法。 - SouthernYankee65
就像你说的一样!我在我的 Mac 上的音乐中添加了歌词,它们出现在我的 iOS 应用程序中。现在我所要做的就是为我最喜欢的播放列表中的所有 570 首歌曲添加歌词 - 哈哈! - Carl Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接