Giter VIP home page Giter VIP logo

persistentstreamplayer's Introduction

PersistentStreamPlayer

Handles the playing of an audio file while streaming, and saves the data to a local URL as soon as the stream completes. Battle-tested in the production version of Calm

Installation

Add this to your Podfile

pod 'PersistentStreamPlayer'

Usage

PersistentStreamPlayer *remoteAudioPlayer = [[PersistentStreamPlayer alloc] initWithRemoteURL:myHTTPURL
                                                                                     localURL:myFileURL];
remoteAudioPlayer.delegate = self;
[remoteAudioPlayer play];

Features

  • streaming of audio file, starting playback as soon as first data is available
  • also saves streamed data to a file URL as soon as the buffer completes
  • simple play, pause and destroy methods (destroy clears all memory resources)
  • ability to seamlessly loop the audio file. call player.looping = YES
  • exposes timeBuffered, helpful for displaying buffer progress bars in the UI
  • handles re-starting the audio file after the buffer stream stalls (e.g. slow network)
  • does not keep audio file data in memory, so that it supports large files that don't fit in RAM

The PersistentStreamPlayerDelegate protocol has some helpful event indicators, all optional:

/* called when the data is saved to localURL */
- (void)persistentStreamPlayerDidPersistAsset:(PersistentStreamPlayer *)player;

/* called when the audio file completed */
- (void)persistentStreamPlayerDidFinishPlaying:(PersistentStreamPlayer *)player;

/* called when the play head reaches the buffer head */
- (void)persistentStreamPlayerStreamingDidStall:(PersistentStreamPlayer *)player;

/* called as soon as the asset loads with a duration, helpful for showing a duration clock */
- (void)persistentStreamPlayerDidLoadAsset:(PersistentStreamPlayer *)player;

/* on failure to load asset */
- (void)persistentStreamPlayerDidFailToLoadAsset:(PersistentStreamPlayer *)player;

persistentstreamplayer's People

Contributors

tsheaff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

persistentstreamplayer's Issues

Not working with endless streams (radio streams)

Thanks for your work.
i've tried to get this to work with radio streams which are endless stream , but it did not work

override func viewDidLoad() {
         super.viewDidLoad()
       let filemgr = FileManager.default
       // let currentPath = filemgr.currentDirectoryPath
        let dirPaths = filemgr.urls(for: .documentDirectory, in: .userDomainMask)

        let docsDir = dirPaths[0].path
        print("docsDir = \(docsDir)")
       let url = URL(string: "http://mp3channels.webradio.antenne.de/oldies-but-goldies")!
        let player = PersistentStreamPlayer(remoteURL: url, localURL: dirPaths[0])
       player?.delegate = self
       
       player?.play()
       print("loaded")

     }

any hint please

Implement seekToTime that guarantees that the bits save to the disk in the proper order

I'm not aware of good documentation on what order the bits will stream to resourceLoader:shouldWaitForLoadingOfRequestedResource:

I left a comment in the code about this here

So right now I believe it's only guaranteed to work if you only ever seek back rather than forward. I believe large forward seeks allow the OS to never fetch any of the bits that occurred in the middle. Anyone have more domain expertise on how the system handles seeks?

Player starts randomly when Screen is locked

Hey there,

I've build in the PersistentStreamPlayer and works as expected!

However, I'm facing some issues when the iPhone locked, or when unlocking the iPhone. When unlocking the Screen, the player starts playing.

I'm using the AppDelegate class to stop the player right away, but it's still playing for about 0.5 seconds.

Another case is when starting the player, stopping it, locking the screen & then activating the screen (Not unlocking). The player starts playing then.

The second case is only in iOS 13, the first case even in lower versions.

Any ideas on how I can fix this? Do you need some more infos?

readyToPlay events fires only once video is down loading entirely

The readyToPlay fires only once video is down loading entirely, instead of shortly after the video started streaming. I've found that this is because the player is making range requests at the end of the file early on (I guess this is related to how mp4 are encoded) and they are only responded once the corresponding data is fetched, which is when the file is downloaded. I don't remember the specific yet, but what I observed in the requests passed to shouldWaitForLoadingOfRequestedResource was something like:

  • range: 0-2
  • range: 9900 - 10000
  • range: 2-...

for a file of byte length 10000. You get the idea. The second request is not responded to until all the file is downloaded, since the data is downloaded in the order it's written in the file. This is delaying the ready to play event

Stop or Play Next

Hi, some background, I am using the player in a music app as the music player. So skip songs in playlists etc.. I have integrated the persistent stream player into our project and it works so far as:

  • Play a stream, persistence, download etc.
  • Pause

However, I can't see in the documentation how to skip to another song/track? I can only see the destroy method?

Any guidance appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.