Как получить текст песни «Сейчас исполняется» в iOS10 (Swift 3)

Я хочу отобразить текст песни, которая в данный момент воспроизводится системным проигрывателем 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, я пробовал 2 подхода, и оба они всегда возвращают 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 возвращает ноль?


person dandepeched    schedule 05.04.2017    source источник
comment
В наши дни большая часть контента iTunes защищена либо FairPlay DRM, либо Apple Music (также защищена FairPlay? Не знаю.), и этот тип контента всегда возвращает nil MPMediaItemPropertyAssetURL. Вы должны использовать его только как музыкальный автомат, где iOS воспроизводит музыку для вас. Более сложные варианты использования невозможны.   -  person Rhythmic Fistman    schedule 05.04.2017
comment
Вы пытались получить доступ, как показано ниже? let lyric = nowPlaying?.lyrics let assetUrl = nowPlaying?.assetURL также обратите внимание, что   -  person Bluewings    schedule 05.04.2017
comment
@RhythmicFistman это не так, потому что мой контент не является контентом iTunes Store. Но я все равно перепроверил следующий метод, который возвращает false (это означает, что в песнях нет DRM): nowPlaying?.hasProtectedAsset   -  person dandepeched    schedule 05.04.2017
comment
@Bluewings Я только что попробовал, и оба возвращают nill   -  person dandepeched    schedule 05.04.2017


Ответы (2)


Я не знаю, почему он не работал, но похоже, что тот же код теперь работает нормально. Может быть, это как-то связано с синглтоном, который я сейчас использую для экземпляра игрока. Вот версия Swift 3, которая работает на 100%:

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
    }
}
person dandepeched    schedule 22.04.2017
comment
NotificationCenter.default.post(newSongNotification as Notification) создает ошибку, а nowPlaying всегда возвращает ноль. Почему ? @dandepeched - person Davender Verma; 18.11.2019
comment
@dandepected, что он все еще возвращает nil . Я использую выше, как. NowPlayingController.sharedController.getLyrics() - person Davender Verma; 18.11.2019
comment
Стихи всегда нулевые, не могли бы вы мне помочь? - person Yogesh Patel; 21.02.2021

Я знаю, что это немного старо, но я только что потратил около 4 часов на изучение того, как читать тексты из файла MP3, если в нем есть тексты. Я использую AVAudioPlayer, а не MPMusicPlayerController. Господи, это так чертовски просто...

Swift 5.3 для macOS (не знаю, работает ли это для iOS, но думаю, что да)

import AVFoundation

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

Обратите внимание, что он возвращает необязательный параметр, поэтому лучше проверить его на ноль. Надеюсь, это сэкономит кому-то часы исследований.

См. документацию Apple здесь.

person SouthernYankee65    schedule 01.10.2020
comment
Спасибо за информацию. Тем не менее, я попробовал это для многих песен в своем музыкальном проигрывателе iOS, и свойство текста было нулевым для каждой из них. :-( - person Carl Smith; 11.12.2020
comment
Я не разрабатываю для iOS, но мне кажется странным, что если тексты песен встроены в ваши mp3-файлы (или другие типы мультимедиа), это не работает для вас. Документация разработчика по ссылке в ответе показывает, что этот метод действителен для всех версий iOS до 4.0. - person SouthernYankee65; 13.12.2020
comment
Большое значение имеет то, встроены ли тексты песен в mp3-файлы. Мое единственное предположение о том, почему это не работает, заключается в том, что они не встроены. Я тоже нахожу это странным (и грустным). Но я ценю информацию! - person Carl Smith; 14.12.2020
comment
Это имело бы смысл. Если их нет, то возврат будет нулевым. Чтобы проверить это, импортируйте mp3 в Music и добавьте некоторые тексты, затем измените URL-адрес файла, чтобы он указывал на место, где Music хранит его, или синхронизируйте его с устройством iOS и протестируйте его, или протестируйте его с файлом, который, как вы знаете, есть лирика. Просто мысль. - person SouthernYankee65; 15.12.2020
comment
Именно так, как вы сказали! Я добавил текст к песне в приложении «Музыка» на своем Mac, и он появился в моем приложении для iOS. Теперь все, что мне нужно сделать, это добавить тексты для всех 570 песен в моем любимом плейлисте - LOL! - person Carl Smith; 15.12.2020