简体   繁体   中英

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. 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? 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?

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. That was this one: Streaming and playing an 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. There is a lot to get precisely correct.

MPMoviePlayerController can play audio files. 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.

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:

[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.

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. 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

@interface ViewController : UIViewController {

NSString *videoURL;

}

@property (nonatomic, strong) NSString *videoURL;

    (IBAction) tv;

And in the 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

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 .

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. Most of what you need is in Audio Queue Services in the AudioToolbox framwork.

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.

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.

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.

You can use the AVPlayer class from the AVFoundation framework to stream audio from local files or from a remote server. The AVPlayer class will notify you about readiness to play or about the need to buffer more data.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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