25

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!

derekahc
  • 910
  • 2
  • 12
  • 20

5 Answers5

66

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

    }
Sumit Mundra
  • 3,891
  • 16
  • 29
  • Is it as easy as init'ing it with a URL? This actually streams the audio? – derekahc Nov 01 '12 at 05:21
  • Mmm alright. I'll give this a try. I was under the impression you had to mess with the server to set up streaming, or at least set some kind of streaming protocol. – derekahc Nov 01 '12 at 19:56
  • 4
    The difference here is `AVPlayer` is capable of streaming where `AVAudioPlayer` is not. Confusing difference! – jocull Jun 19 '13 at 14:45
  • 1
    I believe there is a mistake here: you should not play until the status is ready. In other words `[self.songPlayer play];` should go in `observeValueForKeyPath` when the `songPlayer.status == AVPlayerStatusReadyToPlay` – Bjorn Roche Jan 19 '14 at 22:49
  • I can't play with url: http://www.slobodnyvysielac.sk/redata/other/play.php?file=informacna%20vojna%20-%202015-02-10%20hudo.mp3 – Bkillnest Feb 17 '15 at 18:38
  • Why should I wait 10 seconds, before AVPlayer will be played track with 10 mb size? It's not stream I think... Looks line we need to use AudioToolbox only – Sergey Stadnik Jun 28 '17 at 11:51
  • Its working fine in iOS 10 and xcode 8.If you are unable to play and you are using http url then add app trasnport security in info.plist – Surjeet Rajput Jun 29 '17 at 09:56
15

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.

tumtumtum
  • 1,052
  • 9
  • 11
  • 1
    Audjustable is now known as StreamingKit (the link above will redirect) and seems like a decent foundation for http streaming and other kinds of playback. – Hugh Aug 11 '15 at 03:35
  • Only library I found that worked so far, Great work. – Ahmed Elashker Nov 27 '16 at 10:20
2

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

Aaron Vegh
  • 5,217
  • 7
  • 48
  • 75
  • Does the m3u file have to be on the server? That is to say, can the file be present locally on the iPhone (or I create it locally when needed)? – FuzzyBunnySlippers Jan 10 '14 at 12:55
  • There's no reason it wouldn't work, but practically speaking, a local file would play right away anyway; you likely wouldn't notice a difference. – Aaron Vegh Jan 10 '14 at 20:11
  • No, I mean the MP3 is on the remote server and I know the address of it. But I can't necessarily create the .m3u file there. So I want to create the .m3u file locally which references the url. Does that make sense? – FuzzyBunnySlippers Jan 10 '14 at 20:57
  • Yes, it makes sense, but doesn't work. See https://stackoverflow.com/questions/41112283/avplayer-not-playing-m3u8-from-local-file – Igor Camilo Jul 12 '17 at 13:57
0

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.

Iain Smith
  • 9,230
  • 4
  • 50
  • 61
0

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