【问题标题】:Displaying Artwork for .MP3 file显示 .MP3 文件的图稿
【发布时间】:2015-05-14 17:31:23
【问题描述】:

我目前正在尝试在 ImageView 中显示本地存储的 .MP3 曲目的专辑插图。有谁知道如何在 Swift 中获取这幅作品以完成此任务?

我找到了这个解决方案 (iOS AVFoundation: How do I fetch artwork from an mp3 file?),但代码是用 Objective C 编写的。我只是想抓取嵌入在我的 MP3 中的图像并将其显示在我的 ImageView 中。

我查看了 MPMediaItemArtwork 的 API 文档并找到了一个示例,该示例也完成了我在 Objective C 中尝试完成的工作(http://www.codeitive.com/0zHjkUjUWX/not-able-to-get-the-uiimage-from-mpmediaitempropertyartwork.html),但无法提出解决方案。我的代码如下:

import UIKit
import AVFoundation
import MediaPlayer

class ViewController: UIViewController {
let audioPath:NSURL! = NSBundle.mainBundle().URLForResource("SippinOnFire", withExtension: "mp3")

@IBOutlet var artistImage: UIImageView!
@IBOutlet var trackLabel: UILabel!
@IBOutlet var artistLabel: UILabel!
@IBOutlet var sliderValue: UISlider!
var player:AVAudioPlayer = AVAudioPlayer()


@IBAction func play(sender: AnyObject) {


    let audioInfo = MPNowPlayingInfoCenter.defaultCenter()
println(audioInfo)


    player.play()
    //println("Playing \(audioPath)")


    let playerItem = AVPlayerItem(URL: audioPath)
    let metadataList = playerItem.asset.metadata as! [AVMetadataItem]


    for item in metadataList {
        if let stringValue = item.value {
           println(item.commonKey)
            if item.commonKey == "title" {
                trackLabel.text = stringValue as? String
            }
            if item.commonKey  == "artist" {
                artistLabel.text = stringValue as? String
            }
            if item.commonKey  == "artwork" {
                if let audioImage = UIImage(data: item.value as! NSData) {
                    let audioArtwork = MPMediaItemArtwork(image: audioImage)
                    println(audioImage.description)
                }
           }


        }
    }
}
@IBAction func pause(sender: AnyObject) {

    player.pause()
}
@IBAction func stop(sender: AnyObject) {

    player.stop()
    player.currentTime = 0;
}
@IBAction func sliderChanged(sender: AnyObject) {

    player.volume = sliderValue.value

}

override func viewDidLoad() {
    super.viewDidLoad()

             var error:NSError? = nil

    player = AVAudioPlayer(contentsOfURL: audioPath!, error: &error)

    player.volume = 0.5;

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

这是我的示例 .mp3 文件的屏幕截图。正如您所看到的,在 Finder 的“获取信息”部分中确实可以看到专辑插图。我还在我的 iTunes 中打开了 .mp3 文件,以确保并确认其中的“获取信息”部分以及“艺术品”选项卡下有艺术品。

但是,当尝试使用 commonKey 将图像分配给我的 imageView 时,我发现“艺术品”没有 commonKey。

谢谢

【问题讨论】:

    标签: swift media-player artwork


    【解决方案1】:

    把你的sn-p代码改成这个(我已经测试过了):

    我在感兴趣的地方添加了注释的 println 行,请随意取消注释以查看发生了什么。

       for item in metadataList {
            if item.commonKey == nil{
                continue
            }
    
            if let key = item.commonKey, let value = item.value {
                //println(key)
                //println(value)
                if key == "title" {
                    trackLabel.text = value as? String
                }
                if key  == "artist" {
                    artistLabel.text = value as? String
                }
                if key == "artwork" {
                    if let audioImage = UIImage(data: value as! NSData) {
                      //println(audioImage.description)
                        artistImage.image = audioImage
                    }
                }
            }
        }
    

    更新:对这段代码进行一些清理

    for item in metadataList {
    
        guard let key = item.commonKey, let value = item.value else{
            continue
        }
    
       switch key {
        case "title" : trackLabel.text = value as? String
        case "artist": artistLabel.text = value as? String
        case "artwork" where value is NSData : artistImage.image = UIImage(data: value as! NSData)
        default:
          continue
       }
    }
    

    更新:对于 Swift 4

    for item in metadataList {
    
        guard let key = item.commonKey?.rawValue, let value = item.value else{
            continue
        }
    
       switch key {
        case "title" : trackLabel.text = value as? String
        case "artist": artistLabel.text = value as? String
        case "artwork" where value is Data : artistImage.image = UIImage(data: value as! Data)
        default:
          continue
       }
    }
    

    【讨论】:

    • 完美!这是对我有用的解决方案!谢谢你的帮助。那么使用 .metadata 而不是 .commonmetadata 是否正确?一个只是比另一个更深入地覆盖元数据吗?致敬和欢呼!
    • 这里是 Swift 4 的最新语法:link
    【解决方案2】:

    编辑/更新 Swift 4 或更高版本

    import MediaPlayer
    
    
    var nowPlayingInfo: [String: Any] = [:]
    let playerItem = AVPlayerItem(url: url)
    let metadataList = playerItem.asset.metadata
    
    for item in metadataList {
        switch item.commonKey {
        case .commonKeyTitle?:
            nowPlayingInfo[MPMediaItemPropertyTitle] = item.stringValue ?? ""
        case .commonKeyType?:
            nowPlayingInfo[MPMediaItemPropertyGenre] = item.stringValue ?? ""
        case .commonKeyAlbumName?:
            nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = item.stringValue ?? ""
        case .commonKeyArtist?:
            nowPlayingInfo[MPMediaItemPropertyArtist] = item.stringValue ?? ""
        case .commonKeyArtwork?:
            if let data = item.dataValue,
                let image = UIImage(data: data) {
                nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: image.size) { _ in image }
            }
        case .none: break
        default: break
        }
    }
    

    let audioInfo = MPNowPlayingInfoCenter.default()
    audioInfo.nowPlayingInfo = nowPlayingInfo
    

    注意:您必须调用 beginReceivingRemoteControlEvents() 否则它将无法在实际设备上运行。您还需要设置您的应用背景模式(音频和 AirPlay)并将您的 AVAudioSession 类别设置为 AVAudioSessionCategoryPlayback 并将其设置为活动:

    do {
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay])
        print("Playback OK")
        try AVAudioSession.sharedInstance().setActive(true)
        print("Session is Active")
    } catch {
        print(error)
    }
    

    【讨论】:

    • 我已经尝试了上面的代码,但是没有列出“艺术品”的 commonKey,因此图像必须存储在文件的其他位置。当我打印我的 commonKey 项目时,所有显示的是 [标题类型版权专辑名艺术家] 如果我在文件上“获取信息”,我可以在预览部分以及“艺术作品”选项卡下清楚地看到 mp3 的艺术作品iTunes。但是,没有“艺术品” commonKey 可用于捕获这一点。
    • 它正在从文件中提取信息,您的歌曲可能没有任何艺术作品。确保您的 MP3 文件嵌入了艺术作品
    • 我更新了我的问题,加入了曲目信息的屏幕截图。如您所见,.mp3 中嵌入了艺术品。我没有对 iTunes 中的“艺术作品”选项卡进行第二次屏幕截图,但艺术作品也出现在那里。
    • 你能把文件的链接发给我在这里测试一下吗?
    • 更新了我的问题..我编辑了我的代码以使用 playerItem.asset.metadata 而不是 playerItem.asset.commonmetadata (我假设它是相似的,只是包含文件的更详细的元数据?)我现在可以将“艺术品”视为可用的 commonKey。但是,运行时出现错误:(致命错误:在展开可选值时意外发现 nil)。我不确定我是否更接近莱昂纳多建议的解决方案,而是使用元数据,但我肯定会看到更多使用此提取的字段。
    【解决方案3】:

    试试这个:

    似乎有时 iOS 8 在第一次尝试获取此信息时返回 nil:

    if let audioCenter = MPNowPlayingInfoCenter.defaultCenter(){
            if let audioInfo = audioCenter.nowPlayingInfo{
                if let artwork = audioInfo[MPMediaItemPropertyArtwork] as? MPMediaItemArtwork
                {
                    var image: UIImage? = artwork.imageWithSize(artwork.bounds.size)
    
                    if image == nil {
                        image = artwork.imageWithSize(artwork.bounds.size);
                    }
    
                    if image != nil{
                        println("image loaded")
                    }
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 2013-03-29
      • 2018-02-15
      • 1970-01-01
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多