25
votes

I'm hearing some conflicting reports about this. What I'm trying to do is stream an mp3 file from a URL. I've done hours of research, but I cannot find any good guides on how to do this, or even what kind of audio player I should use.

Some friends tell me that AVPlayer can stream mp3, but the Apple documentation says it can't. I've poured over Matt Gallagher's audio streamer (http://www.cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html), but that code was made a good while ago, and I'm new enough to this that it's hard to work through the autoreleases and retains and all that.

The audio I'm trying to stream is a fairly large mp3 file from a libsyn server, with a URL of format..

http://traffic.libsyn.com/podcastname/episode.mp3

All I need to do is grab it and start playing, with the ability to pause and scrub. So first things first, CAN AVPlayer stream mp3's? And if so, does anybody have any guides or code they can point me to? And if not, is there any kind of audio player class that can stream audio?

I've tried creating an AVPlayerItem, initialized with the URL, then adding it to an AVPlayer, but I'm getting a ton of Error Loading... and Symbol Not Found... errors. I'd appreciate any information on this, thank you!

5
Matt Gallagher's audio streamer has been updatedParesh Navadiya
Not since 2010, though, right?derekahc

5 Answers

66
votes

try this

 -(void)playselectedsong{

        AVPlayer *player = [[AVPlayer alloc]initWithURL:[NSURL URLWithString:urlString]];
        self.songPlayer = player;
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(playerItemDidReachEnd:)
                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:[songPlayer currentItem]];
        [self.songPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];
        [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress:) userInfo:nil repeats:YES];



    }
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

        if (object == songPlayer && [keyPath isEqualToString:@"status"]) {
            if (songPlayer.status == AVPlayerStatusFailed) {
                NSLog(@"AVPlayer Failed");

            } else if (songPlayer.status == AVPlayerStatusReadyToPlay) {
                NSLog(@"AVPlayerStatusReadyToPlay");
                [self.songPlayer play];


            } else if (songPlayer.status == AVPlayerItemStatusUnknown) {
                NSLog(@"AVPlayer Unknown");

            }
        }
    }

    - (void)playerItemDidReachEnd:(NSNotification *)notification {

     //  code here to play next sound file

    }
15
votes

You can also try my open source Audjustable library which supports HTTP streaming. It's based on Matt's AudioStreamer but has been tidied, optimised and updated to support multiple data sources (non HTTP) and gapless playback.

https://github.com/tumtumtum/audjustable.

2
votes

In addition to Sumit Mundra's answer, which helped me a lot, I found that this technique doesn't actually stream MP3 files from a remote server. When I implemented this, the file downloaded synchronously, blocking my UI, before playing. The way to properly stream the MP3 that I found worked very well was to point to an M3U file. This is just a text file with an .m3u extension which contains a link to the original MP3. Point Sumit's code at that file instead, and you have a stream that starts playing immediately.

This is the place I found that information: http://www.soundabout.net/streammp3.htm

0
votes

Matt Gallagher's AudioStreamer was updated 2 months ago https://github.com/mattgallagher/AudioStreamer/commits/master

But for what your looking for check out the sample code StichedStreamPlayer http://developer.apple.com/library/ios/#samplecode/StitchedStreamPlayer/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010092

It uses an AVPlayer object and if you look at method - (IBAction)loadMovieButtonPressed:(id)sender you should be able to follow how it sets up the AVPlayer Object.

0
votes

Aaron's post about using an m3u file instead of an mp3 worked for me. I also found that AVPlayer was picky about the m3u syntax. For example, when I tried the following, I was unable to get a valid duration (it was always indefinite), and relative paths didn't work:

#EXTM3U
#EXTINF:71
https://test-domain.com/90c9a240-51b3-11e9-bb69-c1300ce2348f.mp3

However, after updating the m3u file to the following, both issues were resolved:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:70
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:70.000,
8577d650-51b3-11e9-8e69-4f2b085e94aa.mp3
#EXT-X-ENDLIST