1

Web サーバーからストリームの一部であるビデオ フラグメントをフェッチし、アプリ内で連続して再生する iOS アプリに取り組んでいます。いくつかの調査の後、AVQueuePlayer を使用することにしました。サーバーから MP4 ファイルを取得して NSData オブジェクトに格納するたびに、AVPlayerItem を作成してキューに追加します。また、次のアイテムに進む AVPlayerItemDidPlayToEndTimeNotification 通知をリッスンします。私が直面している問題は、ムービー フラグメントから別のフラグメントに進むたびに発生する小さなラグです。iMovie でフラグメントを結合しようとしましたが、フラグメントがいつ終了し、別のフラグメントが開始するかを判断できませんでした。連続するフラグメント間の小さな一時停止/ラグを取り除くにはどうすればよいですか?

これが私のコードです:

import UIKit
import MediaPlayer
import AVFoundation

class WatchStream: UIViewController, StreamManagerDelegate {

var subscriber : Subscriber!

//Model object responsible for fetching mp4 fragments
var streamManager = StreamManager()

var queue : AVQueuePlayer!


override func viewDidLoad() {
    super.viewDidLoad()

    //Set up the manager
    streamManager.streamID = subscriber.streamid
    streamManager.delegate = self

    //Register for notification once movie player finished
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "AVPlayerFinishedPlaying:", name:AVPlayerItemDidPlayToEndTimeNotification, object: nil)

    queue = AVQueuePlayer()
    var playerLayer = AVPlayerLayer(player: queue)
    playerLayer.frame = self.view.bounds
    self.view.layer.insertSublayer(playerLayer, below: self.navigationController!.navigationBar.layer)

}

//Delegate method notifying that a new fragment is ready to be watched
func streamManagerLoadedStream(fragment: Int, manager: StreamManager) {
    var url = streamManager.fetchFragmentToPlay()
    if url == nil {return}

    var playerItem = AVPlayerItem(URL: url!)
    queue.insertItem(playerItem, afterItem: nil)
    queue.play()
}

//Method called once name:AVPlayerItemDidPlayToEndTimeNotification fires
func AVPlayerFinishedPlaying(notification : NSNotification) {
    //We need to switch to second one
    queue.advanceToNextItem()

    if queue.status == AVPlayerStatus.ReadyToPlay {
        queue.play()
    }
}

}

繰り返しますが、私の問題は AVQueuePlayer を進めるときです。そこにあり得ないこの遅れを引き起こしています。ムービー フラグメントは小さく (それぞれ 1 ~ 2 秒)、ストリームとして連続しているはずです。2 つの AVQueuePlayers と 2 つの AVPlayerLayers を使用してみましたが、問題は解決しませんでした。

また、MPMoviePlayerController を使用して、再生が終了するたびに contentURL を更新しようとしました。ラグは消えませんでした。

どんな手掛かり?

4

1 に答える 1

2

AVQueuePlayer の代わりに AVPlayer で AVMutableComposition を使用します。私は Objective-C を使用しているため、私のサンプルは Swift ではありませんが、Swift コードは非常に似ています。

基本的なロジックは次のとおりです。

  1. AVMutableComposition を作成する

    コンポジション = [AVMutableComposition new];

  2. それに単一の変更可能なトラックを追加します

    AVMutableCompositionTrack *track = [_composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

  3. ループ内: ビデオ フラグメントごとに AVAssetTrack を作成します。

    AVURLAsset* アセット = ...;

    AVAssetTrack *assetTrack = [[asset trackWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

    CMTimeRange timeRange = assetTrack.timeRange;

  4. 再生したい正確な時間にフラグメントをトラックに追加します

    [track insertTimeRange:timeRange ofTrack:assetTrack atTime:時間エラー:&error];

    1. 作曲を再生する

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition]; myPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];

    ...

于 2015-03-06T18:43:02.163 に答える