使用AVPlayer播放rtsp://实时流

4
我想在iPhone设备上使用AVPlayer播放直播流。同时,我还希望从这个流中获取CVPixelBufferRef以供下一步使用。
我使用Apple指南创建播放器。目前,当我尝试播放本地存储的视频文件时,这个播放器工作得很好,当我尝试播放这个AppleSampleStremURL - http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8 - 它也能正常工作。
问题出现在我想播放rtsp://这样的流时: rtsp://192.192.168.1:8227/TTLS/Streaming/channels/2?videoCodecType=H.264 代码 - 几乎所有的代码都是使用Apple提供的指南完成的,但无论如何:
准备资产进行播放
- (void)initialSetupWithURL:(NSURL *)url
{
    NSDictionary *assetOptions = @{ AVURLAssetPreferPreciseDurationAndTimingKey : @YES,
                                    AVURLAssetReferenceRestrictionsKey : @(AVAssetReferenceRestrictionForbidNone)};
    self.urlAsset = [AVURLAsset URLAssetWithURL:url options:assetOptions];
}

准备播放器。
- (void)prepareToPlay
{
    NSArray *keys = @[@"tracks"];
    __weak SPHVideoPlayer *weakSelf = self;
    [weakSelf.urlAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf startLoading];
        });
    }];
}

- (void)startLoading
{
    NSError *error;
    AVKeyValueStatus status = [self.urlAsset statusOfValueForKey:@"tracks" error:&error];
    if (status == AVKeyValueStatusLoaded) {
        self.assetDuration = CMTimeGetSeconds(self.urlAsset.duration);
        NSDictionary* videoOutputOptions = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)};
        self.videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:videoOutputOptions];
        self.playerItem = [AVPlayerItem playerItemWithAsset: self.urlAsset];

        [self.playerItem addObserver:self
                          forKeyPath:@"status"
                             options:NSKeyValueObservingOptionInitial
                             context:&ItemStatusContext];
        [self.playerItem addObserver:self
                          forKeyPath:@"loadedTimeRanges"
                             options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
                             context:&ItemStatusContext];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(playerItemDidReachEnd:)
                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:self.playerItem];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(didFailedToPlayToEnd)
                                                     name:AVPlayerItemFailedToPlayToEndTimeNotification
                                                   object:nil];

        [self.playerItem addOutput:self.videoOutput];

        self.assetPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];

        [self addPeriodicalObserver];
        NSLog(@"Player created");
    } else {
        NSLog(@"The asset's tracks were not loaded:\n%@", error.localizedDescription);
    }
}

这里出现了问题 - AVKeyValueStatus status = [self.urlAsset statusOfValueForKey:@"tracks" error:&error]; - 这行代码中使用rtsp:// URL会返回AVKeyValueStatusFailed 出错信息:
Printing description of error:
Error Domain=AVFoundationErrorDomain Code=-11800 
"The operation could not be completed" 
UserInfo=0x7fd1ea5a8a10 {NSLocalizedFailureReason=An unknown error occurred (-12936), 
NSLocalizedDescription=The operation could not be completed,
NSURL=rtsp://192.168.1.168:8556/PSIA/Streaming/channels/2?videoCodecType=H.264,
NSUnderlyingError=0x7fd1ea53f830 "The operation couldn’t be completed.
(OSStatus error -12936.)"}

我也寻找了问题:

  1. 第一个 - 尝试使用苹果提供的样例应用程序StitchedStreamPlayer,但在播放想要播放的流时会出现几个不同的错误。
  2. 第二个 - 尝试同时使用两个建议,fileURLWithPath返回的URL不正确,例如:rtsp://192.168.1.168:8556/PSIA/Streaming/channels/2?videoCodecType=H.264 --file:///,所以我猜这是不正确的。
  3. 根据AppleDev的建议,尝试使用不同的方法创建AvPlayer,例如[AVPlayer playerWithPlayerItem:playerItem][AVPlayer playerWithURL:url],但没有改变。还尝试设置AVAsset的不同设置-在initialSetupWithURL中(请参见上面的方法实现)。

所以,问题是AVPlayer支持播放rtsp://流吗? 如果是,是否有人可以提供正确使用的示例?我在代码中做错了什么吗? 如果AvPlayer不支持rtsp://,也许存在一些替代方案?


2
你可以参考VLCKit:(MobileVLC)来处理平台RTSP流。 - Anny
4个回答

2
你尝试过使用MobileVLCKit吗?这真的很容易且效果非常好!我在这里写了一个小例子
如果你想试试,只需在终端中输入pod try ONVIFCamera即可。
以下是如何操作:
var mediaPlayer = VLCMediaPlayer()

// Associate the movieView to the VLC media player
mediaPlayer.drawable = self.movieView

let url = URL(string: "rtsp://IP_ADDRESS:PORT/params")
let media = VLCMedia(url: url)
mediaPlayer.media = media

mediaPlayer.play()

1
基本上可以将rtsp流分成小的mp4容器,并使用自定义的URLAsset将容器推送到AVPlayer中。这是一个实验,仍需要在块之间实现平稳过渡,但像一个想法在这里 https://github.com/MaximKomlev/RTSPAVPlayer

这不是很昂贵吗?好主意,但你有比较使用VLC吗? - Onur Tuna

1

我不知道如何通过AVURLAsset进行rtsp流媒体传输,但可能可以从这里找到一个好的起点。也许对某些人有用。


你最终找到解决方案了吗? - Alex Darsonik
AVFoundation仅支持HTTP Live Streaming(HLS),但您可以查看https://github.com/iMoreApps/ffmpeg-avplayer-for-ios-tvos甚至https://github.com/larrytin/vlc-ios。 - hbk
我看到了这些,更多地是在寻找Mac OS的解决方案,而不是iOs。有一件事:你是否找到了官方支持AVFoundation仅支持HTTP Live Streaming的来源?文档有点稀少。 - Alex Darsonik
实际上不是,反之亦然。 - hbk

0

使用AVPlayer无法播放RTSP流。您分享的链接http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8是HLS流,所以可以正常工作。

您应该在服务器上将RTSP流转换为HLS流,或者找到另一种方法。最有效的方法是在客户端上播放HLS流。但是,如果您没有机会获取HLS流,则可以使用VLC的方法。这种方法效率不高,但可以工作。

我有一篇旧的博客文章介绍了iOS上的VLC。您可以参考一下。

https://medium.com/mobil-dev/lets-make-a-video-player-app-e759c165fd58


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接