2015-11-23 19 views
5

Tôi đang phát âm thanh bằng cách sử dụng AVPlayer. Nó hoạt động tốt. Nhưng Bây giờ tôi cần phải thực hiện một thanh trượt để di chuyển âm thanh về phía trước và phía sau, giống như trình phát nhạc thông thường. Tôi đã sử dụng hàm seekToTime hoạt động tốt với tệp âm thanh cục bộ. Nhưng khi tôi phát bài hát từ url web, chức năng sẽ dừng âm thanh khi tôi chuyển thanh trượt với phạm vi rộng.SeekToTime trong AVPlayer ngừng phát âm thanh trực tuyến, khi chuyển tiếp

Tôi đoán là bài hát đang được tải xuống và nếu tôi di chuyển thanh trượt về phía trước với phạm vi rộng thì có thể hệ thống chưa tải xuống gói dữ liệu bài hát trong thời gian đó, vì vậy nó tạm dừng trình phát.

Cho phép nói rằng tôi chỉ cần nhấn nút để phát bài hát nhưng bây giờ tôi di chuyển thanh trượt ngay lập tức từ 0 đến 100 giây. Trong trường hợp này, hệ thống không hoạt động và dừng trình phát. Do thiếu gói dữ liệu cho thời gian đó.

Có ai biết cách khắc phục sự cố này hoặc có cách tiếp cận nào khác không. Tôi đang sử dụng SWIFT để phát triển. Tôi cũng sẽ sử dụng bất kỳ thư viện nào nếu nó hoạt động nhanh chóng. Đây là chức năng của tôi:

func forward() { 
    timeGap = slider.value 
    let preferredTimeScale : Int32 = 1 
    let targetTime : CMTime = CMTimeMake(timeGap, preferredTimeScale) 

    player.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero) 

} 

Cảm ơn trước.

Trả lời

8

Câu trả lời này dựa trên câu trả lời này: https://stackoverflow.com/a/7195954/765298. Bất kỳ và tất cả các tín dụng nên đến đó vì đây chỉ là một bản dịch để nhanh chóng.

Bạn có quyền giả định rằng khi tìm kiếm về phía trước một phần chưa được đệm nhưng người chơi sẽ dừng lại. Vấn đề là nó vẫn đệm dữ liệu, nhưng không tự động khởi động khi nó đã sẵn sàng. Vì vậy, để nói lại câu trả lời liên quan đến nhanh chóng:

Để thiết lập các quan sát viên của bạn:

player.currentItem?.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .New, context: nil) 
player.currentItem?.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .New, context: nil) 

Lưu ý, rằng để có thể quan sát giá trị, thông qua self cần phải kế thừa từ NSObject.

Và để xử lý chúng:

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

    guard keyPath != nil else { // a safety precaution 
     super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) 
     return 
    } 

    switch keyPath! { 
     case "playbackBufferEmpty" : 
      if player.currentItem!.playbackBufferEmpty { 
       print("no buffer") 
       // do something here to inform the user that the file is buffering 
      } 

     case "playbackLikelyToKeepUp" : 
      if player.currentItem!.playbackLikelyToKeepUp { 
       self.player.play() 
       // remove the buffering inidcator if you added it 
      } 
    } 
} 

Bạn cũng có thể nhận được thông tin về thời gian avaiable dao động từ hiện đang chơi AVPlayerItem (bạn có thể acces nó qua player.currentItem nếu bạn chưa tạo nó cho mình). Điều này cho phép bạn chỉ ra cho người dùng biết các phần nào của tệp đã sẵn sàng.

Như mọi khi bạn có thể đọc một số chi tiết trong tài liệu: AVPlayerItemAVPlayer

Để đọc thêm về giá trị khóa quan sát (KVO): here

+0

tôi đã nhận thấy rằng khi tôi bắt đầu một video trực tiếp dòng các bộ đệm trống ngay từ đầu ('playbackBufferEmpty == true') và cờ playbackBufferEmpty không bao giờ thay đổi trạng thái của nó thành false. Có cách nào để tự khởi động bộ đệm bằng AVFoundation không? – svrs

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