Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add safari camera encode support #116

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

alcolmenar
Copy link

@alcolmenar alcolmenar commented Jul 28, 2023

A number of things to happen to fully enable Safari support due its lack of support for Web specific APIs used:

  • Determine a method to enable a method generate VideoFrame to pipe through the VideoEncoder
  • Remove usage of MediaStreamTrackProcessor in camera_encoder.rs and implement method
  • Determine a method encode Audio using the opus codec (Safari doesn't support AudioEncoder) most likely going to need a 3rd party library for this
  • Remove usage of MediaStreamTrackerProcessor in microphone_encoder.rs and implement method
  • Determine a method to decode the Audio stream in peer_decoder.rs and pipe output through the Web Audio APIs (Safari doesn't support AudioDecoder)
  • Remove usage of MediaStreamTrackGenerator and implement above

Fixes #58

Copy link
Member

@darioalessandro darioalessandro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good!! lets see what we can use for audio https://crates.io/crates/opus-oxide

yew-ui/src/model/encode/camera_encoder.rs Outdated Show resolved Hide resolved
@alcolmenar
Copy link
Author

looking good!! lets see what we can use for audio https://crates.io/crates/opus-oxide

@darioalessandro looks like this package doesn't have any code in it

@darioalessandro
Copy link
Member

Goddam! Clickbait

…asms

Created a wrapper interface for the worklets
Implemented worklet usage in peer_decoder and microphone_encoder
Cleaned up camera encoder
Fixed issues with video rendering in peer decoder
@alcolmenar
Copy link
Author

alcolmenar commented Aug 24, 2023

Starting from https://github.com/mmig/opus-encdec, I had decided to try to use ScriptProcessorNodes to obtain Audio samples -> Encode -> Transmit -> Decode -> Audio samples, but it introduced a ton of delay and artifacts. Also ScriptProcessorNodes are deprecated for good reason. I then tried to use AudioWorklets, but the repo only had a Worklet created for the encoding side so I forked the repo here and created one. Also, I had to rebuild the js / wasm files to make sure all of the source files show up in the same file so it loads easier when adding the JS as a module. I added Google's FreeQueue library (a high performance ring buffer), but I had to change a little bit because it was using SharedArrayBuffer's as its backing and they aren't in the GlobalAudioWorkletScope.

Created an AudioWorkletCodec struct that essentially creates and interfaces with the worklet and implemented its usage in the both microphone_encoder and peer_decoder using the respective worklets.

As far as testing, I was able to test video on Safari. However, for Audio, after a ton of debugging and trying to figure out what was going on, Safari disables a bunch of Web API features on newer versions if you aren't connecting to a HTTPS endpoint so I wasn't able test Audio fully. Audio from newer Safari browsers to Chrome works, but not very well. I'm not sure how much of that is due to the non-HTTPS endpoint.

Video from Chrome to Safari iOS works. Safari iOS has HTTPS issues as well. Safari iOS to Chrome Video has issues. It seems like it is due to this.). Suspended AudioContexts were common in Chrome using AudioBufferSources, but switching to AudioWorklets made it less common.

@alcolmenar alcolmenar marked this pull request as ready for review August 24, 2023 11:36
@alcolmenar
Copy link
Author

What do you think about adding the forked worklet repo as a submodule to this project?

@darioalessandro
Copy link
Member

@alcolmenar you are a rockstar!

I'll review your PR today.

To use https with safari you could use ngrok to expose your localhost in the internet and get valid https certs: https://ngrok.com/

@alcolmenar
Copy link
Author

alcolmenar commented Aug 24, 2023

To use https with safari you could use ngrok to expose your localhost in the internet and get valid https certs: https://ngrok.com/

I tried that. Maybe I'm doing something wrong but I figured it wouldn't work since there are a few ports that need to be exposed and a free account only allows 1 at a time. Were you able to get a full test in using it?

@darioalessandro
Copy link
Member

@alcolmenar I am looking at this now

@alcolmenar
Copy link
Author

@darioalessandro how does it look?

@darioalessandro
Copy link
Member

darioalessandro commented Aug 31, 2023

You are a legend my friend!!

POC is fantastic! audio sounds great!!

Video is a bit slow but I am sure that if we work together we can make it fast!!

Screenshot 2023-08-30 at 9 13 36 PM

@darioalessandro
Copy link
Member

Hey @alcolmenar ! I noticed that there's compiled wasm both encoder/decoder.js workers? do you have the source code for these and license?

@alcolmenar
Copy link
Author

alcolmenar commented Sep 2, 2023

Hey @alcolmenar ! I noticed that there's compiled wasm both encoder/decoder.js workers? do you have the source code for these and license?

I forked the opus-encdec repo here https://github.com/alcolmenar/opus-encdec/tree/audio-worklet and made changes to it to create the decoderWorker Worklet. I think I need to update the license though because I also pulled in a Ring Buffer implementation from Google labs https://github.com/GoogleChromeLabs/web-audio-samples/tree/main/src/audio-worklet/free-queue

The compiled wasm is an emscripten compilation of the c implementation of libopus and speexdsp. The license is in the repo already

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Safari 16.5 and iOS Chrome
2 participants