简体   繁体   English

将音频从服务器流式传输到iPhone

[英]Streaming audio from server to iPhone

I'm looking to stream some audio files I have on my server to an iPhone-client application I'm writing. 我正在寻找将我服务器上的一些音频文件流式传输到我正在编写的iPhone客户端应用程序。 Some of the audio files can be rather large in size, even after compression. 即使在压缩之后,一些音频文件的大小也可能相当大。 My question is, is there a Cocoa framework that helps me with buffering the audio so it becomes available to the user while the rest is being brought down the pipes? 我的问题是,是否有一个Cocoa框架可以帮助我缓冲音频,以便用户可以使用它而其余部分被放下管道? If not, can anyone point me in the right direction to learn more about the technologies required to make such a thing happen using Objective-C/Cocoa? 如果没有,任何人都可以指出我正确的方向,以了解更多关于使用Objective-C / Cocoa实现这样的事情所需的技术吗?

A definitive resource on buffering and compression of audio from a server<->client infrastructure would be ideal. 从服务器< - >客户端基础设施缓冲和压缩音频的权威资源将是理想的。

Brad mentioned a post that I wrote to stream audio via HTTP. Brad提到了我写的一篇帖子,用于通过HTTP传输音频。 That was this one: Streaming and playing an MP3 . 就是这个: 流媒体和播放MP3 I don't mean to be the person that links to his own blog but it does kind of address your question. 我不是故意成为链接到他自己的博客的人,但它确实解决了你的问题。

In regards to how hard the problem is to solve, you'll notice I've made 4 updates to that post (way more than I've done for anything else), fixing threading errors, memory leaks and network buffering issues. 关于解决问题的难度,您会注意到我已经对该帖子进行了4次更新(比其他任何方式都做得更多),修复了线程错误,内存泄漏和网络缓冲问题。 There is a lot to get precisely correct. 有很多东西要准确无误。

MPMoviePlayerController can play audio files. MPMoviePlayerController可以播放音频文件。 If you initialize the object with a content url (this can be an Mp3 file on a server, for instance) it will stream the file and play it back. 如果使用内容URL初始化对象(例如,这可以是服务器上的Mp3文件),它将流式传输文件并进行回放。

The initialization looks like this: 初始化如下所示:

NSURL *theURL = [NSURL urlWithString:@"http://yourdomain.com/yourmediafile.mp3"];

MPMoviePlayerController* yourPlayerController = [[MPMoviePlayerController alloc] initWithContentURL:theURL];

From there you can pop up a playback view that will show a slider for scrubbing through the content, and it will fill in the slider bar as the content buffers. 从那里你可以弹出一个播放视图,它将显示一个用于擦除内容的滑块,它将填充滑块作为内容缓冲区。

[yourPlayerController shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight];
[self presentMoviePlayerViewControllerAnimated:yourPlayerController];

Or you could just make it play and create your own UI: 或者您可以让它播放并创建自己的UI:

[yourPlayerController.moviePlayer play];

This method of playback will cut off the audio when the screen locks unless you tell the app to run in the background in the info.plist file. 除非您告诉应用程序在info.plist文件中的后台运行,否则此播放方法将在屏幕锁定时切断音频。

I know by now that you hopefully have solved your problem. 我现在知道你希望已经解决了你的问题。 But just incase. 但只是因为。 If you want a straight forward solution, you can always get the embeded code or any other link and make an html file out of it. 如果你想要一个直接的解决方案,你总是可以得到嵌入代码或任何其他链接,并从中制作一个html文件。 Like 喜欢

<html>
<body>
<script type="text/javascript">
  var embedBaseUrl = 'http://www.tv.net/';
  var embedChannelId = 13;
  var embedSize = [300,250];
  var embedAutoplay = true;
</script>
<script type="text/javascript"src="http://www.tv.net/assets/js/embed.js"></script>
</body>
</HTML>

ViewController.h ViewController.h

@interface ViewController : UIViewController {

NSString *videoURL;

}

@property (nonatomic, strong) NSString *videoURL;

    (IBAction) tv;

And in the ViewController.m 并在ViewController.m中

@synthesize videoURL;

    (IBAction) tv {

    self.videoURL = @"http://dl.dropbox.com/x/xxxxxxxx/HTML/tv.html";

    VideoViewController *videoViewController = [[VideoViewController alloc] initWithNibName:nil bundle:nil];

    videoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; videoViewController.videoURL = self.videoURL;

    [self presentViewController:videoViewController animated:YES completion:nil]; }

And then in VideoViewController.h 然后在VideoViewController.h中

IBOutlet UIWebView *videoView;

NSString *videoURL; NSString *videoHTML;

}

@property(nonatomic, retain) IBOutlet UIWebView *videoView; @property(nonatomic, retain) NSString *videoURL; @property(nonatomic, retain) NSString *videoHTML;

    (void) embedTV;

VideoViewController.m

@synthesize videoView, videoURL, videoHTML;

    (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; }

    (void)embedTV {

    videoHTML = [NSString stringWithFormat:@"\ \ \ \ iframe {position:absolute; top:50%%; margin-top:-130px;}\ body {background-color:#000; margin:0;}\ \ \ \ \ \ ", videoURL];

    [videoView loadHTMLString:videoHTML baseURL:nil]; }
        (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib.

    videoView.backgroundColor = [UIColor blackColor]; videoView.opaque = NO;

    [self embedTV]; }

Now in my example I referred to video stream, but you get the point, you can stream or play what you want. 现在在我的例子中我提到了视频流,但是你明白了,你可以流式传输或播放你想要的东西。 Simply just use UIWebView . 只需使用UIWebView

Unfortunatally, you are going to have a bit of work in front of you. 不幸的是,你会在你面前做一些工作。 I had to do this for an iPhone project this last summer. 去年夏天,我不得不为iPhone项目做这件事。 Most of what you need is in Audio Queue Services in the AudioToolbox framwork. 您需要的大部分内容都在AudioToolbox框架中的音频队列服务中。

Working with audio queue services is kind of tricky, you will have to implement a bunch of callbacks to tell it how to processes your packets after they come off the network. 使用音频队列服务有点棘手,您必须实现一堆回调来告诉它如何在数据包离开网络后对其进行处理。

Someone, I think Matt Gallagar, had some sample code on a blog that was okay, and there is a bunch of stuff on Apple's Core Audio Mailing List. 有人,我认为Matt Gallagar在博客上有一些示例代码没问题,Apple的核心音频邮件列表上有很多东西。

I did find that I ended up needing to not relay on NSURL Connection to do the network part, because my didrecievedata delegate method was not firing often enough. 我确实发现我最终不需要在NSURL Connection上进行中继来执行网络部分,因为我的didrecievedata委托方法没有经常触发。

Sorry I could not just drop in a few lines of code as an example here, but the class I wrote to do this came in at around 400 lines. 对不起,我不能在这里插入几行代码作为示例,但是我写的这个类大约有400行。

You can use the AVPlayer class from the AVFoundation framework to stream audio from local files or from a remote server. 您可以使用AVFoundation框架中的AVPlayer类从本地文件或远程服务器流式传输音频。 The AVPlayer class will notify you about readiness to play or about the need to buffer more data. AVPlayer类将通知您播放的准备情况或缓冲更多数据的需要。

However if you want more control you should definitely use Audio Queue services. 但是,如果您想要更多控制,您肯定应该使用音频队列服务。 Using Audio Queue services is a little bit harder but once you get the hang of it you'll be able to fine-tune the audio playback process the way you want it. 使用音频队列服务有点困难,但是一旦掌握了它,你就能够以你想要的方式微调音频播放过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM