2011-01-14 25 views

Trả lời

0

Nó là, nhưng nó không phải dễ dàng. Matt Gallagher có một số nice post on his blog về phát trực tuyến âm thanh. Để báo cho anh ta về chủ đề:

Nguồn siêu dữ liệu đơn giản nhất là từ tiêu đề HTTP. Bên trong handleReadFromStream: eventType: phương pháp, sử dụng CFReadStreamCopyProperty để sao chép các kCFStreamPropertyHTTPResponseHeader tài sản từ CFReadStreamRef, sau đó bạn có thể sử dụng CFHTTPMessageCopyAllHeaderFields để sao chép các lĩnh vực tiêu đề ra của phản ứng . Đối với nhiều máy chủ âm thanh trực tuyến , tên luồng là một trong số các trường này.

Nguồn khó hơn đáng kể là siêu dữ liệu là các thẻ ID3. ID3v1 là luôn ở cuối tệp (như vậy là vô ích khi phát trực tuyến). ID3v2 là nằm ở đầu để có thể có thêm có thể truy cập được.

tôi chưa bao giờ đọc các thẻ ID3 nhưng tôi nghi ngờ rằng nếu bạn bộ nhớ cache vài trăm kilobyte đầu tiên của tập tin đâu đó như nó tải, mở rằng bộ nhớ cache với AudioFileOpenWithCallbacks và sau đó đọc kAudioFilePropertyID3Tag với AudioFileGetProperty bạn có thể là có thể đọc dữ liệu ID3 (nếu nó tồn tại ). Giống như tôi đã nói mặc dù: Tôi đã không bao giờ thực sự làm điều này vì vậy tôi không biết chắc chắn rằng nó sẽ làm việc.

+0

Nếu bạn làm được việc này, cho tôi biết. – Moshe

+0

vâng, trong iTunes khi tệp .m3u đang phát trực tuyến, thông tin bài hát và nghệ sĩ sẽ tự động cập nhật. có lẽ ID3v2 được phát trực tuyến-- ở đầu mỗi bản nhạc, như bạn đã nói. vì vậy có lẽ nó chỉ là vấn đề của một người nghe sự kiện đang chờ siêu dữ liệu-- tôi sẽ tiếp tục tìm kiếm. – miketucker

+0

@mike yep.Hãy xem mã của Matt, phiên bản mới nhất là trên GitHub. Nó sẽ cung cấp gợi ý tốt đẹp. – Moshe

20

Không chắc chắn câu hỏi này vẫn còn thực tế cho tác giả của nó, nhưng có thể nó sẽ giúp ai đó. Sau hai ngày đau đớn, tôi đã điều tra rằng nó khá đơn giản. Dưới đây là đoạn code mà làm việc cho tôi:

AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:<here your http stream url>]]; 

[playerItem addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionNew context:nil]; 

AVPlayer* player = [[AVPlayer playerWithPlayerItem:playerItem] retain]; 
[player play]; 

và sau đó:

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object 
         change:(NSDictionary*)change context:(void*)context { 

    if ([keyPath isEqualToString:@"timedMetadata"]) 
    { 
     AVPlayerItem* playerItem = object; 

     for (AVMetadataItem* metadata in playerItem.timedMetadata) 
     { 
     NSLog(@"\nkey: %@\nkeySpace: %@\ncommonKey: %@\nvalue: %@", [metadata.key description], metadata.keySpace, metadata.commonKey, metadata.stringValue); 
     } 
    } 
} 

Vậy là xong. Tôi không biết tại sao Apple không cung cấp tài liệu cho AVPlayerItem mẫu này để truy cập "tiêu đề" của luồng là tính năng chính cho âm thanh phát trực tuyến thực. Trong "Tham khảo Khung nền tảng AV", họ nói về "timedMetadata" ở đâu đó khi cần thiết. Và mẫu của Matt không hoạt động với tất cả các luồng (nhưng AVPlayer làm).

+0

Không chắc chắn tại sao điều này không bao giờ được đánh dấu là câu trả lời chính xác, nhưng nó thực sự cần được đánh dấu. Trong luồng liên tục, đối với ứng dụng radio, bạn có thể làm gì để nhận siêu dữ liệu sau khi tệp âm thanh hiện tại đã phát và tệp mới bắt đầu phát? – user717452

+0

Mã trên sẽ được gọi bất cứ khi nào giá trị 'timedMetadata' bị thay đổi. Do đó, khi phát một luồng web (như radio internet), 'observValueForKeyPath: ofObject: change: context:' sẽ được trigged trên thay đổi. – rckoenes

+0

Ở trên nên được chọn như là câu trả lời đúng không biết tại sao như vậy, nhưng nó giúp tôi rất nhiều. Cảm ơn nhiều. –

3

trong nhanh chóng 2.0 nhận được luồng thông tin siêu dữ liệu âm nhạc:

PlayerItem.addObserver(self, forKeyPath: "timedMetadata", options: NSKeyValueObservingOptions.New, context: nil) 

thêm phương pháp này:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 

    //Atualiza Nome Musica 
    if keyPath == "timedMetadata" { 
     if let meta = PlayerItem.timedMetadata { 
      print("Novo Metadata \(meta)") 
      for metadata in meta { 
       if let nomemusica = metadata.valueForKey("value") as? String{ 
        LB_NomeMusica.text = nomemusica 
        if NSClassFromString("MPNowPlayingInfoCenter") != nil { 
         let image:UIImage = UIImage(named: "logo.gif")! 
         let albumArt = MPMediaItemArtwork(image: image) 
         var songInfo: [String:AnyObject] = [ 
          MPMediaItemPropertyTitle: nomemusica, 
          MPMediaItemPropertyArtist: "Ao Vivo", 
          MPMediaItemPropertyArtwork: albumArt 
         ] 
         MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = songInfo 
        } 
       } 
      } 
     } 
    } 


} 
Các vấn đề liên quan