Giter VIP home page Giter VIP logo

streamingkit's Introduction

StreamingKit

StreamingKit (formally Audjustable) is an audio playback and streaming library for iOS and Mac OSX. StreamingKit uses CoreAudio to decompress and playback audio (using hardware or software codecs) whilst providing a clean and simple object-oriented API.

The primary motivation of this project was to decouple the input data sources from the actual player logic in order to allow advanced customizable input handling such as HTTP progressive download based streaming, encryption/decryption, auto-recovery, dynamic-buffering. StreamingKit is the only streaming and playback library that supports dead-easy gapless playback between audio files of differing formats.

Main Features

  • Free OSS.
  • Simple API.
  • Easy to read source.
  • Carefully multi-threaded to provide a responsive API that won't block your UI thread nor starve the audio buffers.
  • Buffered and gapless playback between all format types.
  • Easy to implement audio data sources (Local, HTTP, AutoRecoveringHTTP DataSources are provided).
  • Easy to extend DataSource to support adaptive buffering, encryption, etc.
  • Optimised for low CPU/battery usage (0% - 1% CPU usage when streaming).
  • Optimised for linear data sources. Random access sources are required only for seeking.
  • StreamingKit 0.2.0 uses the AudioUnit API rather than the slower AudioQueues API which allows real-time interception of the raw PCM data for features such as level metering, EQ, etc.
  • Power metering
  • Inbuilt equalizer/EQ (iOS 5.0 and above, OSX 10.9 Mavericks and above) with support for dynamically changing/enabling/disabling EQ while playing.
  • Example apps for iOS and Mac OSX provided.

Installation

StreamingKit is available as a Cocoapod. You can also simply copy all the source files located inside StreamingKit/StreamingKit/* into your Xcode project.

Example

There are two main classes. The STKDataSource class which is the abstract base class for the various compressed audio data sources. The STKAudioPlayer class manages and renders audio from a queue DataSources. By default STKAudioPlayer will automatically parse URLs and create the appropriate data source internally.

Play an MP3 over HTTP

STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];

[audioPlayer play:@"http://www.abstractpath.com/files/audiosamples/sample.mp3"];

Gapless playback

STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];

[audioPlayer queue:@"http://www.abstractpath.com/files/audiosamples/sample.mp3"];
[audioPlayer queue:@"http://www.abstractpath.com/files/audiosamples/airplane.aac"];

Intercept PCM data just before its played

[audioPlayer appendFrameFilterWithName:@"MyCustomFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
{
   ...
}];

More

More documentation is available on the project Wiki

Authors and Contributors

Copyright (c) 2012-2019, Thong Nguyen (@tumtumtum)

streamingkit's People

Contributors

ablinov avatar abuharsky avatar atlithorn avatar corprew avatar danielgindi avatar derpoliuk avatar diegostamigni avatar dylancom avatar haritowa avatar johnboiles avatar kampfgnu avatar kwillick avatar obrhoff avatar pcbeard avatar ravenwang avatar reindernijhoff avatar richardgroves avatar sergiou87 avatar tepmnthar avatar terryso avatar tumtumtum 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  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

streamingkit's Issues

Some title won't play or play wrong

Hi,

I'm trying this framework and first try seems ok. But with some titles, it doesn't.
With AVPlayer, titles are playing ok.
With AudioPlayer, ther don't.
For exemple :
http://moulinsard.dyndns.org:23424/cds/resource/20704/MEDIA_ITEM/MP3-0/ORIGINAL,1?authToken=5b5971fd4e0842999394c999cd6a2d39
or
http://moulinsard.dyndns.org:23424/cds/resource/24246/MEDIA_ITEM/MP3-0/ORIGINAL,1?authToken=edb6c68d602c4619b9edcb3290411ba8

And some plays at the wrong speed. this one :
http://moulinsard.dyndns.org:23424/cds/resource/20818/MEDIA_ITEM/MP3-0/ORIGINAL,1?authToken=46cb6759a75246baa02cfcad15da42be

So, for a first try, I'm not convince this player is reliable :-(

Maybe it's just a little bug ?
Or maybe not.

Continual allocation of NSDate objects in [AudioPlayer startInterval]

Hi Thong,

The following line in the startInterval method of the AudioPlayer module causes a continually increasing number of NSDate objects to be allocated. The auto-release pool which wraps this code doesn't drain frequently enough and my application's memory footprint continued to grow by roughly a megabyte every 5 minutes.

[playbackThreadRunLoop runMode:NSDefaultRunLoopMode
                    beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];

One solution would be to drain the pool manually after each iteration of the while loop or change the above line to:

NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:10];
[playbackThreadRunLoop runMode:NSDefaultRunLoopMode beforeDate:date];

I have tested this code change and it does fix this issue but am interested to hear your thoughts.

Cheers

Nothing is playing in iOS 6.1.3 and iPhone 3GS

Hi,

Im trying your demo project on my iPhone 3GS with iOS 6.1.3.

Nothing is playing, but on simulator with iOS 6.1 is working and on my iPhone 4 with iOS5 is working too.

What is wrong? Can you help me please?

UISlider ends before audio playback

It's a problem even in an example project in iOS 7 - UISlider reaches end 2-3 seconds before end of the locally playing file. Have been digging into this and found no possible reason.

How to get the http audio stream metadata

I'm currently using AVPlayerItem to stream my audio source. I would like to use audjustable but I need to be able to get my songs title.

Currently I'm using KVO on avplayeritem.timedMetadata.

How can I get the audio stream metadata in audjustable

By the way, thank for the great work !

MP3 streams are giving wrong AudioPlayerErrorQueueCreationFailed error

When I try to to play an MP3 stream I always get the AudioPlayerErrorQueueCreationFailed error even though the stream plays fine.

This is the example code from your Readme:

STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
audioPlayer.delegate = self;
[audioPlayer play:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"];

Playing this results in the delegate called with the error but the stream plays fine. Since our app is actually handling errors by stopping playback and skipping to the next stream this is kind of a big deal.

With Audjustable you never reported the error back to the delegate:

Please report the correct error back, since the queue was obviously created just fine (audio is playing), or don't report this nonsense error.

Cancel datasource that was queued

Hi,

I'm not seeing a method in the player to undo the the queuing up of a datasource. I have the case of a playlist that people can reorder on the fly at the last minute and in that case, I need to cancel the queuing of a streaming song.

Let me know how I should approach this.

Also I'm still on the Audjustable lib. What's the risk of me upgrading to the SK stuff?

Thanks a lot!!!

Random access for .WAV file not working

Hi, I'm able to randomly access (scrub) remote MP3 files, but when I try the same with a remote WAV file (16-bit PCM, 8kHz, MONO) it doesn't work. And after attempting to scrub, the player ceases to play anything else without a reboot. I've done packet captures to verify that the Range headers and so on are all the same.

Resume after audio interruption

Currently, I'm using the following code but it doesn't seem to work at all.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioInterruptionNotification:) name:AVAudioSessionInterruptionNotification object:nil];

  • (void)audioInterruptionNotification:(NSNotification *) aNotification {
    DLog(@"Interrupt %@", aNotification);
    NSDictionary *dict = [aNotification userInfo];
    NSUInteger typeKey = [[dict objectForKey:@"AVAudioSessionInterruptionTypeKey"] unsignedIntegerValue];
    DLog(@"%d", typeKey == AVAudioSessionInterruptionTypeBegan);
    if (typeKey == AVAudioSessionInterruptionTypeBegan) {
    [_player pause];
    } else {
    [_player resume];
    }
    }

I can see all of the messages printing out in the console but music is not resume for some reason. Is there something that I can do here to fix it? Thanks a lot

Add new mime type for ACC

In HttpDataSource the mime type for the AAC format is @"audio/aac" but there is other mime type in use for the AAC format.

To be able to stream my audio file I've add the mime type @"audio/aacp" for kAudioFileAAC_ADTSType.

Other mime type are in use see : http://en.wikipedia.org/wiki/Advanced_Audio_Coding

PS : I've tried to do a pull request, but i don't know how to do it yet ...

Volume Control

Can you give a short example how to control the volume of the Audio Player?!
I tried a lot but failed to control the Volume of streamed audio by Slider

progress is always 0 when duration is 0

I am playing a stream (transcoded subsonic stream) that has no duration. I can't get progress because of those lines in progress method:

if (retval > duration)
{
    retval = duration;
}

progress is calculated but then set to 0 because duration is 0

Difference between progress and duration when player stops

Hi,

Me again :)

I'm queuing a remote track right before the completion of the playing track is it transitions nicely.

However for some files/tracks this doesn't work because the player stops even though the next track is queued up. This happens consistently with a few particular tracks.

So I added a log when didFinishPlayingQueueItemId is captured and noticed this

Finished playing 2 - reason: 0 - progress 139.891365 - duration 139.908802

It basically stops playing before the duration.

What can cause this? Or what can cause the track not not transition to the next? Thanks!!

Progress value invalid for formats with indeterminate length

If you try to play a file format for which the length cannot be calculated from the header, e.g. Sun AU, this call:

AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &audioDataByteCount);

doesn't produce an error, but it does set audioDataByteCount to 0xffffffff (i.e. a 32-bit -1 converted unsigned to 64-bit.) This makes the progress bar invalid since it thinks the duration is incredibly large.

You can change audioDataByteCount to a UInt32 and you still get back the same value as a UInt32.

Although it's a bit of a hack, this fixes the problem:

        error = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &audioDataByteCount);

        if (!error && audioDataByteCount != 0xffffffff)
            currentlyReadingEntry->audioDataByteCount = audioDataByteCount;

Update tag

Can you please create a tag for 0.0.8?

Handling timeout

I have encountered a problem when the network or server does not disconnect from the CFStream but has slowed down enough to cause playback to stop. Eventually I would want audjustable to timeout from this state.

I have implemented a rudimenteray timeout in application code (outside of audjustable, when triggered it just calls stop) but I'm wondering whether this should be handled internally?
Either by audioplayer.m or the datasources?
Also the only method I know of is to keep track of read bytes and on a separate thread check to see that number change, wondering if there isn't a more concrete method?

Atli.

Is it possible to change the queue ID

Hi,

I'm just starting to use your library and it's helping me tremendously so thank you very much for the work.

I was perusing the code and I don't think it's feasible but wanted to double check if it was possible to change the queue ID of a data source? If yes, how.

Thanks a lot

Rebuffering does not work

I am testing a player based on StreamingKit under bad network conditions - to force rebuffering. It seems that when the rebuffering state is entered there is no way to buffer a AudioPlayerBuffersNeededToStart number of buffers and then restart the playback. Instead each new buffer enqueued is immediately consumed by the AudioPlayer queue - with the result that no sound is actually played but the playhead slowly moves forward until all data is eventually donwloaded. Does anyone know a way to make rebuffering work?

How can i get available (buffering) duration?

Nice job man! I have two questions:
1 How can i get available (buffering) duration?
2 Is it possible implement processing callback for Equalizer or DSP and if yes, how can i do this?
Thanks!

How does gapless playback work?

This readme for this project says that it supports gapless playback.

However I cannot figure out how to having things play back in a gapless way. I call queueDataSource:withQueueItemId: twice and when the first song finishes, the second doesn't start automatically.

Save audio file when Streaming?

Hey
Thanks for great open source!.

My question is, can I save audio file when at this same time streming from remote source?

AudioSessionInitialize doesn't work

Hey,

I'm trying to make Audjustable work in background, but AudioSessionInitialize doesn't seem to do the trick.

I added:

AudioSessionInitialize(NULL, NULL, NULL, NULL); AudioSessionSetActive (true);

to the audioPlayerViewPlayFromHTTPSelected method in AppDelegate.m, but after pressing the home button stream pauses playing. What should I do?

M

How to play audio that I recorded with "*.caf"

Hi,How to play audio that I recorded with "*.caf"?
record format is like this:

    memset(&recorderState.mDataFormat, 0, sizeof(recorderState.mDataFormat));
    recorderState.mDataFormat.mFormatID = kAudioFormatiLBC;
    recorderState.mDataFormat.mSampleRate = 8000.0;
    recorderState.mDataFormat.mChannelsPerFrame = 1;
    recorderState.mDataFormat.mBitsPerChannel = 0;
    recorderState.mDataFormat.mBytesPerPacket = 38;
    recorderState.mDataFormat.mBytesPerFrame = 0;
    recorderState.mDataFormat.mFramesPerPacket = 160;
    recorderState.mDataFormat.mFormatFlags = 0;

Is there a way to play songs from the user's library?

Hey, I'm just starting a project that plays both streamable content from the internet and songs from the user library. This framework has been pretty helpful so far.

However, I'm stuck in an issue: when dealing with the users local library the MPMediaItemPropertyAssetURL value returns a URL in the form of "ipod-library://item/item.mp3?id=[song_id]", which when passed to the framework doesn't seem to play it properly. Is there support for such URL types? If not, is there a way to parse or change this url to a compatible form?

Any help is appreciated, thank you for your time.

Network conditioner

If you are streaming via http and the network is bad. (Simulated on device via Settings->Developer->Network Link Conditioner)

The buffers will dry up and playback stops. However if you rectify the condition (disable Network Link Conditioner) sometimes Audjustable will not recover. No indication of any error, just no playback. It might be a timeout issue on the underlying CFStream, I'll see if I can narrow it down.

Playing audio on iPad

First, great framework. You did a great job cleaning up Gallaghers AudioStreamer which I've been using for about six months.

However, the audio player plays on an iPad device (running ios6) but no sound comes out of the speakers. I commented the #ifdef TARGET_OS_IPHONE in AudioPlayer.m, but still no sound. Other sounds play fine.

Any ideas?

Crash when playing unsupported file formats

I tried playing an AMR file, which STILL isn't supported in iOS. The player figures out it's an AMR file, but crashes here:

        memcpy((char*)bufferToFill->mAudioData + bytesFilled, (const char*)inputData + packetOffset, packetSize);

in handleAudioPackets. This is because:

error = AudioQueueNewOutput(&currentlyPlayingEntry->audioStreamBasicDescription, AudioQueueOutputCallbackProc, (__bridge void*)self, NULL, NULL, 0, &audioQueue);

returns an error in createAudioQueue and doesn't finish initializing. I changed handleAudioPackets to make sure the queue was created in createAudioQueue, and that seems to prevent a crash.

if (audioQueue == nil)
{
    [self createAudioQueue];
    if (audioQueue == nil) return;
}

FYI.

Handling failing connections

If you loose network connection mid-stream, audjustable sends AudioPlayerInternalStateError to the delegate. This is perfect, it means I can fall back to other streams.

On the other hand, if you try to connect to a stream while you already don't have network connection (as opposed to loosing it mid-stream) then we do NOT get AudioPlayerInternalStateError, instead we're stuck in AudioPlayerInternalStateWaitingForData forever.

I would guess that connecting to the stream should just fail immediately? And send the appropriate error?

Play different music in a short period of time,the player can not be stopped

In my viewController, call the playInfo: function many times in a short period of time,then pop the viewController(viewDidDisappear: is called),music is still playing。

-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];

[_audioPlayer stop];
_audioPlayer.delegate = nil;
_audioPlayer = nil;

}

-(void)playInfo:(NSDictionary *)info
{
self.musicInfo = info;

if (_audioPlayer) {
    [_audioPlayer stop];
    _audioPlayer.delegate = nil;
}
_audioPlayer = [[AudioPlayer alloc] init];
_audioPlayer.delegate = self;

NSURL *url = [self getPlayURL:info];
[_audioPlayer setDataSource:[_audioPlayer dataSourceFromURL:url] withQueueItemId:url];
}

Memory leak in CoreFoundationDataSource.m

I think the method "close" should look like this

-(void) close
{
if (stream)
{
CFReadStreamClose(stream);
+ CFRelease(stream);
stream = 0;
}
}

otherwise we get memory leak.

HttpDataSource line 66 I thank it will memory leaks

httpHeaders = (__bridge NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)copyPropertyMessage);

I thank should

if(httpHeaders) {
CFRelease((__bridge CFTypeRef)httpHeaders);
}
httpHeaders = (__bridge NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)copyPropertyMessage);

and

-(void)dealloc {
if(httpHeaders) {
CFRelease((__bridge CFTypeRef)httpHeaders);
}
}

tks, I think AudioFileStreamOpen functions parameter kAudioFileM4AType should can setting

I think line 1305

error = AudioFileStreamOpen((__bridge void*)self, AudioFileStreamPropertyListenerProc, AudioFileStreamPacketsProc, kAudioFileM4AType, &audioFileStream);

should like AudioStreamer

AudioFileTypeID fileTypeHint = [AudioPlayer hintForFileExtension:self.fileExtension];
error = AudioFileStreamOpen((__bridge void*)self, AudioFileStreamPropertyListenerProc, AudioFileStreamPacketsProc, fileTypeHint, &audioFileStream);

//
// hintForFileExtension:
//
// Generates a first guess for the file type based on the file's extension
//
// Parameters:
// fileExtension - the file extension
//
// returns a file type hint that can be passed to the AudioFileStream
//

  • (AudioFileTypeID)hintForFileExtension:(NSString *)fileExtension
    {
    AudioFileTypeID fileTypeHint = kAudioFileMP3Type;;
    if ([fileExtension isEqual:@"mp3"])
    {
    fileTypeHint = kAudioFileMP3Type;
    }
    else if ([fileExtension isEqual:@"wav"])
    {
    fileTypeHint = kAudioFileWAVEType;
    }
    else if ([fileExtension isEqual:@"aifc"])
    {
    fileTypeHint = kAudioFileAIFCType;
    }
    else if ([fileExtension isEqual:@"aiff"])
    {
    fileTypeHint = kAudioFileAIFFType;
    }
    else if ([fileExtension isEqual:@"m4a"])
    {
    fileTypeHint = kAudioFileM4AType;
    }
    else if ([fileExtension isEqual:@"mp4"])
    {
    fileTypeHint = kAudioFileMPEG4Type;
    }
    else if ([fileExtension isEqual:@"caf"])
    {
    fileTypeHint = kAudioFileCAFType;
    }
    else if ([fileExtension isEqual:@"aac"])
    {
    fileTypeHint = kAudioFileAAC_ADTSType;
    }
    return fileTypeHint;
    }

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.