superpoweredSDK / Low-Latency-Android-iOS-Linux-Windows-tvOS-macOS-Interactive-Audio-Platform

🇸Superpowered Audio, Networking and Cryptographics SDKs. High performance and cross platform on Android, iOS, macOS, tvOS, Linux, Windows and modern web browsers.
https://superpowered.com
1.32k stars 284 forks source link

HLS Looping #777

Open webmonch opened 2 months ago

webmonch commented 2 months ago

Hi,

is it possible to loop HLS file? Can't seem to get it working

ivannador commented 2 months ago

Hello,

No, it is not possible to loop a HLS file.

webmonch commented 2 months ago

Thanks for a quick response @ivannador !

What about progressive download?

gaborszanto commented 2 months ago

A progressive download will have all features, including looping.

webmonch commented 2 months ago

Thanks @gaborszanto!

And how does cachePosition() behave with progressive download? Can it be called right after open(...)?

gaborszanto commented 2 months ago

It gets cached when that point is downloaded.

webmonch commented 2 months ago

Thanks! Really appreciate quick response 🙏

One (hopefully) last question - I am trying to run ReactNative example (with progressive download) and I am getting an error:

PlayerEvent_ConnectionLost: "Network socket error. No internet?"

Both on simulator and on device.

If I change it to HLS streaming - everything works fine.

Song url is from example: https://docs.superpowered.com/audio/samples/splice/SO_PF_74_string_phrase_soaring_Gb.mp3 XCode 15.3 IOS 17.4

All settings are from example project.

webmonch commented 2 months ago

Same on Android. HLS plays fine, progressive download doesn't work.

webmonch commented 2 months ago

@ivannador @gaborszanto we are evaluating this SDK for our company use and are blocked by this issue. I'd really appreciate any tips 🙏

ivannador commented 2 months ago

Did you try a different URL provided by you? If not, please try with this URL: https://creativelycommon-public-assets.s3.eu-west-2.amazonaws.com/cdk.mp3

webmonch commented 2 months ago

@ivannador Yes, this one works. But the one in the example doesn't, though it is a valid url. Is there a way to tell why? To make sure it doesn't happen with urls provided buy us.

Also when I open working url, I get Superpowered::AdvancedAudioPlayer::PlayerEvent_Opened right before Superpowered::AdvancedAudioPlayer::PlayerEvent_ProgressiveDownloadFinished, so playback starts only after download finished.

I expected progressive download to start while the track is being downloaded, or is this not the case?

ivannador commented 2 months ago

Your server has to handle Content-Range in the response header and Range in the request header. Make sure it does, then it'll work. For example S3 supports it by default. This not working with the URL from the example is an issue on our server, we'll fix that.

Well it is ready for playback after PlayerEvent_Opened so you should listen for that. If PlayerEvent_ProgressiveDownloadFinished comes quickly it means it is downloaded or it's already downloaded and loaded from local.

webmonch commented 2 months ago

Thank you.

I am also getting a small click when using loopBetween(3000, 5000, true, 255, false) as you can hear on the video. Is it possible to remove it completely? Happens both on iOS (device + simulator) and MacOS.

https://github.com/superpoweredSDK/Low-Latency-Android-iOS-Linux-Windows-tvOS-macOS-Interactive-Audio-Platform/assets/1910471/1a1af622-1062-43e2-8003-c94d02018789

Here is the file I am using (local playback, not download) https://test-reports-frontend-web.s3.eu-west-2.amazonaws.com/track.mp3

webmonch commented 2 months ago

And regarding seeking in file that is being downloaded, from what I gathered if you seek to the part that hasn't yet been downloaded, nothing plays, is that correct? If yes, is it possible to force download start from a new position?

webmonch commented 2 months ago

@ivannador is it technically possible using buffers and advanced player to implement progressive download with seeking?

My use case is basically this:

From what I gathered, I basically need an HLS player with looping or a progressive download that supports seeking to not downloaded parts.

How can I implement this?

If this is not possible with built-in features, I can implement file downloading in chunks with range header, etc., But how would I integrate this with audio buffers?

ivannador commented 2 months ago

Progressive download works in a linear fashion. It starts to download the audio data continuously, you can only seek to what is already downloaded. I suppose making it possible on server-side to "cut" the track in specific parts and load those chunks with progressive download is possible.

That click in loopBetween seems to be a bug, good catch. It is very prominent with a pure tone you are using, not so much with a more complex waveform like an actual track, but still. We'll provide a fix for that.

As for separately downloading chunks, you can use the AudioInMemory class with append, and openMemory in Advanced Audio Player.

webmonch commented 2 months ago

Could you please describe very high level flow of using AudioInMemory with the mentioned use case?

e.g. when I download first 10% of the file and 10% in the middle of the file. decodeToAudioInMemory per docs decodes entire file. How to I decode non linear chunks and play them with the option to loopBetween?

ivannador commented 2 months ago

Well you can create an AudioInMemory container and append raw PCM data to it while you already opened it with openMemory of AAP. I think you have to make sure that on the server you make downloadable chunks out of the audio track to decode it with Decoder non-linearly.

webmonch commented 1 month ago

Thank you,

Do you think it will possible to add looping to HLS audio file streaming (not real-time, just aac converted to hls) after we purchase a license?

webmonch commented 1 month ago

Also do I need to call any method to inform the player that new data has been appended (when appending compressed data into AiM buffers)?

ivannador commented 1 month ago

We have HLS improvements planned on the longer roadmap, but I can't tell when it will come.

You don't have to inform the player that data has been appended.

webmonch commented 1 month ago

For some reason player doesn't see new sections. I download chunks of HLS every few seconds and append compressed audio to AiM, but player plays only those that were added before openMemory() was called.

What I do:

The reserved field in compressed audio buffer changes so I guess player noticed the chunks but the player plays only first two chunks. What am I missing here?

Screenshot A - when I call play() first time (plays 2 chunks, though 4 are in buffers) Screenshot B - when I call play() again after first play (still plays only 2)

This is compressed buffer so size is in bytes.

Screenshot 2024-05-03 at 12 30 18 Screenshot 2024-05-03 at 12 30 35
gaborszanto commented 1 month ago

Is the size argument for the AudioInMemory (main table) set to 0?

webmonch commented 1 month ago

Yes

compressedAudioBuffer = (Superpowered::AudioInMemory*)Superpowered::AudioInMemory::create(0, 0, 0, false);

ivannador commented 2 weeks ago

Hey @webmonch,

Did you manage to test this with our latest release (2.6.8)?

webmonch commented 2 weeks ago

@ivannador yes but still had issues. Here's the code I am using (based on HLS streaming project for IOS from your examples)

https://gist.github.com/webmonch/5cce8ad2a612941e4e327db89edcea7f

Wrote to your zendesk about it yesterday.