iOS视频流媒体和在设备上存储

28

目前我知道如何流式传输视频并如何下载它,然后再次播放它,但是这里有个棘手的问题:可以流式传输一次,将其存储在设备上,并在未来从设备中播放吗?

这种可能性存在吗?


7
如果将来有人遇到这个问题,这是我发现的粗略解决方案:使用NSURLConnection异步下载视频URL的内容到本地文件中,并在下载了一定部分(对我来说是2 MB)后播放该文件。NSURLConnection的connection:didReceiveData代理方法会起到关键作用。 - Tudor
它并不聪明,因为它并没有完全工作。 - Tudor
3
iPhone操作系统注意事项:NSURLDownload类在iPhone操作系统中不可用,因为直接下载到文件系统是不被推荐的。请改用NSURLConnection类。有关更多信息,请参阅“使用NSURLConnection”。 - Tudor
你尝试过在iPhone上创建HTTP服务器并在文件下载时从本地主机重新流式传输吗? - Steven Veltema
你有检查过这个吗?https://dev59.com/81sW5IYBdhLWcg3w2aKK - Meet Doshi
显示剩余2条评论
5个回答

1

在这里不太确定你是如何获取流的,但可以查看AVAssetWriter、AVAssetWriterInput和AVAssetWriterPixelBufferAdaptor。一旦接收到数据,你应该能够使用以下方法将数据追加到像素缓冲适配器中:

appendPixelBuffer:withPresentationTime:

不确定这对你是否有效,但是通过一些调整,你应该能够使你的输入适应这种方法。有很多设置编写器的示例代码。


嗯...我不确定这个怎么符合整个情况。 - Tudor
你从某个地方接收到了一个视频流吗?如果你能获取到这个流的帧,并将每一帧附加到AVAssetWriterPixelBufferAdaptor中,那么它就会被写入文件,之后你可以从设备上存储的任何位置播放它。 - Robin Rye

1

保存视频非常容易。做类似于这样的事情:

//Saving Movie
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];          
[archiver encodeObject:*MovieObject* forKey:@"MovieObjectDataKey"];
[archiver finishEncoding];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"MovieObjectDefaultsDataKey"];
[archiver release];
[data release];

//Retrieving movie 
NSData *savedMovieData = [[NSUserDefaults standardUserDefaults] objectForKey:@"MovieObjectDefaultsDataKey"];
if (savedMovieData != nil) {
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:savedMovieData];
    *MovieObject* = [[unarchiver decodeObjectForKey:@"MovieObjectDataKey"] retain];
    [unarchiver finishDecoding];
    [savedMovieData release];
    [unarchiver release];
} else {
    //Download Stream of Your Movie
}

你真正需要改变的唯一事情是每个步骤中的 * MovieObject *。


我不确定你在那里做什么?存档是为了什么? - Tudor
MovieObject 是存储电影的变量。只是为了澄清,您已经下载了一部电影并希望将其保存,以便下次再次加载,是吗?还是您正在流式传输电影并希望将其存储在本地变量中? - Dyldo42
我想开始下载视频并开始播放,即使它只下载了部分。这有点像流媒体,但同时也在磁盘缓存。下次播放电影时,将播放磁盘版本。 - Tudor
明白了。你已经可以在下载的同时玩它了吗? - Dyldo42
1
是的,但我使用的方法比较丑陋:在 NSURLConnection 的 connection:didReceiveData 方法中,每隔 10 秒钟,我都从磁盘上重新加载电影,并从之前的播放位置继续播放。当下载完成时,我会最后一次重新加载它。这种方法之所以丑陋,有许多原因,其中最明显的原因是视频重新加载时会出现一个短暂的黑屏。 - Tudor
为了避免黑框,你不能将它重新加载到另一个对象中,然后更改以显示来自该对象的数据并释放第一个对象吗? - Robin Rye

0

我知道你想要实现什么,但我只有一个变通方法。我不得不实现相同的行为,并最终通过从服务器流式传输视频并在流式传输旁边进行下载来解决问题。下次用户尝试流式传输视频时,请确定它是否已下载到磁盘上,否则再次进行流式传输。在正常情况下,视频已经成功下载并可以离线查看。


0

ASIHttpRequest 可能会让你的生活更轻松。

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:@"video.m4v"]; // use [NSBundle mainBundle] to find a better place

从您的代理处,处理此事:

- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;

在你获取数据并实时推送到AVAssetWriter或电影播放器层之前,可以对data进行任何数据转码。完成后,资产仍应保存以便稍后使用。


我看到另一个关于如何下载视频的答案,但你的回答有一个隐藏的有趣部分:“你可以实时地将其推送到AVAssetWriter或电影播放器层中,无论你使用什么”。你能详细说明一下吗?这就是我感兴趣的。 - Tudor
你目前是如何进行视频流传输的?还没有开始吗? - slf

0
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:somePath];

fileURLWithPath:isDirectory:

使用指定的路径初始化并返回一个新创建的NSURL对象,作为文件URL。

+ (id)fileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir

参数

path

NSURL对象将表示的路径。路径应该是一个有效的系统路径。如果路径以波浪线开头,必须首先通过stringByExpandingTildeInPath进行扩展。如果路径是相对路径,则被视为相对于当前工作目录。 传递此参数的nil会产生异常。

isDir

一个布尔值,指定在解析相对路径组件时是否将路径视为目录路径。如果路径表示目录,则传递YES,否则传递NO。 返回值 使用路径初始化的NSURL对象。

可用性

iOS 2.0及更高版本可用。

您不能同时流式传输和保存它,特别是对于大型视频文件,因为Apple文档指出,您必须使用传输流进行HTTP Live Streaming。


我知道文档上说这样做,但我很好奇是否可能绕过它。 - Tudor

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