-
-
Notifications
You must be signed in to change notification settings - Fork 11.4k
Forward audio #3757
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
Forward audio #3757
Conversation
6e948fe
to
2b2cf0a
Compare
Are the BUILD instructions outdated?
|
Seems to be nowhere in the sources? I don't even see a src folder
EDIT: Oh the folder is there just not that file in app/src/util |
Oops, it was not committed, sorry. Fixed. |
|
Aha java is too new (jdk 19). Trying an older version |
It's alive! Note 10 Plus on Android 12. Working well! |
test.mp4 |
Looking forward to this PR! |
Since scrcpy-server is not an Android application (it's a java executable), it has no Context. Some features will require a Context instance to get the package name and the UID. Add a FakeContext for this purpose. PR #3757 <#3757> Co-authored-by: Romain Vimont <[email protected]> Signed-off-by: Romain Vimont <[email protected]>
FakeContext already provides an AttributeSource instance. PR #3757 <#3757> Co-authored-by: Simon Chan <[email protected]>
Audio will be enabled by default (when supported). Add an option to disable it. PR #3757 <#3757> Co-authored-by: Romain Vimont <[email protected]> Signed-off-by: Romain Vimont <[email protected]>
When audio is enabled, open a new socket to send the audio stream from the device to the client. PR #3757 <#3757> Co-authored-by: Romain Vimont <[email protected]> Signed-off-by: Romain Vimont <[email protected]>
Create an AudioRecorder to capture the audio source REMOTE_SUBMIX. For now, the captured packets are just logged into the console. PR #3757 <#3757> Co-authored-by: Romain Vimont <[email protected]> Signed-off-by: Romain Vimont <[email protected]>
Yeah I patched an exe just for fun |
Yes, it is possible to add flac support. On Windows, you need to build an FFmpeg with flac decoding support: https://github.com/rom1v/scrcpy-deps/blob/231e4e819127dc55f1bf394943ba9887c1cb6224/build_ffmpeg_windows.sh#L40-L41 And in scrcpy, you add flac everywhere in addition to opus and aac. Here is the commit for aac: 4601735 PR welcome 😉 |
Similar to --video-codec-options, but for audio. PR #3757 <Genymobile/scrcpy#3757>
This will allow to reuse the same code for audio encoder selection. PR #3757 <Genymobile/scrcpy#3757>
Similar to --video-encoder, but for audio. PR #3757 <Genymobile/scrcpy#3757>
Print the logs on the caller side. This will allow to call the function in another context without printing the logs. PR #3757 <Genymobile/scrcpy#3757>
Add an option to list the device encoders properly. PR #3757 <Genymobile/scrcpy#3757>
When audio capture fails on the device, scrcpy continue mirroring the video stream. This allows to enable audio by default only when supported. However, if an audio configuration occurs (for example the user explicitly selected an unknown audio encoder), this must be treated as an error and scrcpy must exit. PR #3757 <Genymobile/scrcpy#3757>
This prepares the introduction of audio_decoder. PR #3757 <Genymobile/scrcpy#3757>
This will be useful in logs. PR #3757 <Genymobile/scrcpy#3757>
PR #3757 <Genymobile/scrcpy#3757>
Frame consumers may need details about the frame format. PR #3757 <Genymobile/scrcpy#3757>
Add a ring-buffer for bytes. It will be useful for buffering audio. PR #3757 <Genymobile/scrcpy#3757>
If there is exactly one producer, then it can assume that the remaining space in the buffer will only increase until it write something. This assumption may allow the producer to write to the buffer (up to a known safe size) without any synchronization mechanism, thus allowing to read and write different parts of the buffer in parallel. The producer can then commit the write with lock held, and update its knowledge of the safe empty remaining space. PR #3757 <Genymobile/scrcpy#3757>
Play the decoded audio using SDL. The audio player frame sink receives the audio frames, resample them and write them to a byte buffer (introduced by this commit). On SDL audio callback (from an internal SDL thread), copy samples from this byte buffer to the SDL audio buffer. The byte buffer is protected by the SDL_AudioDeviceLock(), but it has been designed so that the producer and the consumer may write and read in parallel, provided that they don't access the same slices of the ring-buffer buffer. PR #3757 <Genymobile/scrcpy#3757> Co-authored-by: Simon Chan <[email protected]>
On Android 11, it is possible to start the capture only when the running app is in foreground. But scrcpy is not an app, it's a Java application started from shell. As a workaround, start an existing Android shell existing activity just to start the capture, then close it immediately. PR #3757 <Genymobile/scrcpy#3757> Co-authored-by: Romain Vimont <[email protected]> Signed-off-by: Romain Vimont <[email protected]>
The new chlayout API has been introduced in FFmpeg 5.1. Use the old channel_layout API on older versions. PR #3757 <Genymobile/scrcpy#3757>
By default, scrcpy mirrors only the video when audio capture fails on the device. Add a flag to force scrcpy to fail if audio is enabled but does not work. PR #3757 <Genymobile/scrcpy#3757>
The components needing delayed frames (sc_screen and sc_v4l2_sink) managed a sc_video_buffer instance, which itself embedded a sc_frame_buffer instance (to keep only the most recent frame). In theory, these components should not be aware of delaying: they should just receive AVFrames later, and only handle a sc_frame_buffer. Therefore, refactor sc_delay_buffer as a frame source (it consumes) frames) and a frame sink (it produces frames, after some delay), and plug an instance in the pipeline only when a delay is requested. This also removes the need for a specific sc_video_buffer. PR #3757 <Genymobile/scrcpy#3757>
If there is only one point, assume the slope is 1. PR #3757 <Genymobile/scrcpy#3757>
A delay buffer delayed all the frames except the first one, to open the scrcpy window immediately and get a picture. Make this feature optional, so that the delay buffer might also be used for audio. PR #3757 <Genymobile/scrcpy#3757>
Expose an option to add a buffering delay (in milliseconds) before playing audio. This is similar to the options --display-buffer and --v4l2-buffer for video frames. PR #3757 <Genymobile/scrcpy#3757>
The audio capture was implemented in AudioEncoder. In order to reuse it without encoding, extract it to a separate class. PR #3757 <Genymobile/scrcpy#3757>
In order to support both encoded and raw audio stream, extract a interface (very minimal, but sufficient to just start and stop). PR #3757 <Genymobile/scrcpy#3757>
Add an alternative AudioRecorder to stream raw packets without encoding. PR #3757 <Genymobile/scrcpy#3757>
Add support for raw (PCM S16 LE) audio codec (a raw decoder is included in FFmpeg). PR #3757 <Genymobile/scrcpy#3757>
For raw audio codec, some audio options are ignored. PR #3757 <Genymobile/scrcpy#3757>
Last month, @yume-chan submitted a working PoC to capture audio on Android. Big thanks for this discovery!
Since then I have worked to properly integrate audio support in scrcpy (capture, encode, transmit, record, decode, resample, play…), and my branch reached a working state (at least on my machine) 🎉
By default, audio is enabled (if supported):
If audio capture fails, then mirroring continues with video only (since audio is enabled by default, it is not acceptable to make scrcpy fail if audio is not available), unless
--require-audio
is set.To disable audio:
If audio is enabled, it is also recorded when recording is enabled:
To play audio in real-time, the audio player implements drift compensation (it attempts to keep audio sample buffering to a certain level, quite low to get low-latency, but not too low to avoid underflow). It is experimental
(I just tinkered with this thing today)(I've made a lot of improvements since the initial MR, and it should work pretty fine), parameters and behavior are hardcoded, some configuration variables might need to be exposed in the future (or not).If you record, the timestamps are computed on the device, so they are not impacted by any jitter/underflow (this is the same as for the video), so the recording is always clean (if you use
--record
of course, not if you capture your audio output on the computer).Like the video, it works over TCP/IP (typically Wifi).
The following options have been renamed:
--codec
->--video-codec
--bit-rate
->--video-bitrate
--codec-options
->--video-codec-options
--encoder
->--video-encoder
And similar options for audio have been added:
--audio-codec
--audio-bit-rate
--audio-codec-options
--audio-encoder
Three audio formats are supported:
scrcpy --audio-codec=opus
scrcpy --audio-codece=aac
scrcpy --audio-codec=raw
(more bandwidth, typically just for testing)It is possible to list the encoders available on the device (video and audio):
If you need a specific encoder, use
--audio-encoder
:When recording, raw audio is not possible (it automatically switches to OPUS). In the future, I might add audio encoding on the client-side specifically for recording, but I don't plan to make it for this audio feature.
I also implemented
--audio-buffer=
similar to existing--display-buffer=
and--v4l2-buffer=
.This branch is in working state.
Since I have refactored A LOT of code, I may have broken things (please tell me!).
Please test, review (good luck, that's a big PR 😉), and report any problem :)
Fixes #14
old
Here is a release build for the current MR for Windows (
audio.115
):scrcpy-win64-PR3757-1.zip
SHA-256: 8a46774889f0d6602e7f94c1e664b7184fdc0f0ccfe4d114045d2a8eefb408f6
scrcpy-win32-PR3757-1.zip
SHA-256: 7b07819377fa87f1a94f5a424b6757590492b32309d59457fb4eb1e543902bd4
Here is a release build for the current MR for Windows (
audio.145
):scrcpy-win64-PR3757-3.zip
SHA-256: 6ef3c45292f5c3b713628e593bbf695be586506cd38a26f038d135cd88d08033
scrcpy-win32-PR3757-3.zip
SHA-256: 06fc50e289494554aa1d86a783960b5fd42268ac18395f224b0ea355aa377dd5