From 160cd03645b8c3e81858e93e30ef30a008f8f25b Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 20 Jul 2026 15:16:17 +0200 Subject: [PATCH 01/12] refactor: remove ffmpeg decoding and use OS apis --- .../build-compilation-dependencies/SKILL.md | 2 + CLAUDE.md | 2 +- .../src/examples/AudioFile/AudioPlayer.ts | 2 - apps/fabric-example/ios/Podfile.lock | 2 +- .../other/disabling-prebuilt-libraries.mdx | 2 +- .../audiodocs/docs/other/runtime-flags.mdx | 8 +- packages/audiodocs/docs/sources/audio-tag.mdx | 2 +- packages/audiodocs/docs/utils/decoding.mdx | 5 +- packages/react-native-audio-api/.clangd | 24 + .../react-native-audio-api/RNAudioAPI.podspec | 2 +- .../src/main/cpp/audioapi/AndroidDecoding.cpp | 500 ++++++++++++++++++ .../src/main/cpp/audioapi/AndroidDecoding.h | 45 ++ .../src/main/cpp/audioapi/CMakeLists.txt | 1 + .../HostObjects/utils/NodeOptionsParser.h | 12 +- .../core/sources/AudioFileSourceNode.cpp | 4 - .../core/sources/AudioFileSourceNode.h | 6 +- .../cpp/audioapi/core/types/AudioFormat.h | 8 - .../cpp/audioapi/core/utils/AudioDecoding.cpp | 168 +++--- .../cpp/audioapi/core/utils/AudioDecoding.h | 13 +- .../core/utils/decoding/SeekDecoderDaemon.cpp | 57 +- .../core/utils/decoding/SeekDecoderDaemon.h | 5 +- .../decoding/IncrementalAudioDecoder.h | 0 .../common/cpp/audioapi/decoding/OSDecoding.h | 26 + .../cpp/audioapi/decoding/OsDecoderBase.h | 66 +++ .../audioapi/libs/ffmpeg/FFmpegDecoding.cpp | 148 +----- .../cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h | 26 +- .../libs/miniaudio/MiniAudioDecoding.h | 3 +- .../ios/audioapi/ios/core/utils/IOSDecoding.h | 46 ++ .../audioapi/ios/core/utils/IOSDecoding.mm | 357 +++++++++++++ .../react-native-audio-api/src/utils/flags.ts | 7 +- .../src/utils/remoteHttpSource.ts | 2 +- .../test-app-screen/src/AudioBufferTest.ts | 53 +- packages/test-app-screen/src/AudioTagTest.ts | 30 +- 33 files changed, 1273 insertions(+), 361 deletions(-) create mode 100644 packages/react-native-audio-api/android/src/main/cpp/audioapi/AndroidDecoding.cpp create mode 100644 packages/react-native-audio-api/android/src/main/cpp/audioapi/AndroidDecoding.h delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/core/types/AudioFormat.h rename packages/react-native-audio-api/common/cpp/audioapi/{libs => }/decoding/IncrementalAudioDecoder.h (100%) create mode 100644 packages/react-native-audio-api/common/cpp/audioapi/decoding/OSDecoding.h create mode 100644 packages/react-native-audio-api/common/cpp/audioapi/decoding/OsDecoderBase.h create mode 100644 packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSDecoding.h create mode 100644 packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSDecoding.mm diff --git a/.claude/skills/build-compilation-dependencies/SKILL.md b/.claude/skills/build-compilation-dependencies/SKILL.md index d8868f273..a8ae88792 100644 --- a/.claude/skills/build-compilation-dependencies/SKILL.md +++ b/.claude/skills/build-compilation-dependencies/SKILL.md @@ -29,6 +29,8 @@ react-native-audio-api/ │ │ └── src/main/cpp/audioapi/ │ │ └── CMakeLists.txt # Actual Android C++ build target │ ├── common/cpp/audioapi/ # Shared C++ (used by all platforms) +│ │ ├── decoding/ # Incremental + OS decoder contracts (no external deps) +│ │ ├── libs/ # Third-party wrappers (FFmpeg, miniaudio, pffft, …) │ │ └── external/ # Prebuilt binaries per platform │ │ ├── android/ # .a static libs (Opus, Ogg, Vorbis, OpenSSL) │ │ ├── iphoneos/ # iOS device .a libs diff --git a/CLAUDE.md b/CLAUDE.md index aec80112e..63161b2ea 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,7 +20,7 @@ packages/custom-node-generator/ # Code generation tooling ### Layers (from JS to hardware) 1. **TypeScript API** (`src/`) — node implementations (`src/core/`), browser passthrough (`src/web-core/`), platform system APIs (`src/system/`), TurboModule specs (`src/specs/`), hooks, events, utils -2. **C++ Engine** (`common/cpp/audioapi/`) — node engine (`core/`), SIMD DSP (`dsp/`), JSI HostObjects, audio events, prebuilt external libraries (`external/`) +2. **C++ Engine** (`common/cpp/audioapi/`) — node engine (`core/`), incremental/OS decoding (`decoding/`), SIMD DSP (`dsp/`), JSI HostObjects, audio events, third-party wrappers (`libs/` — FFmpeg, miniaudio, etc.), prebuilt binaries (`external/`) 3. **Android Native** (`android/`) — CMake + Gradle, Kotlin module, C++ JNI glue (`src/main/cpp/`), Oboe 1.9.3 audio I/O 4. **iOS Native** (`ios/audioapi/ios/`) — Objective-C++ (`.mm`), CocoaPods (`RNAudioAPI.podspec`), CoreAudio I/O diff --git a/apps/common-app/src/examples/AudioFile/AudioPlayer.ts b/apps/common-app/src/examples/AudioFile/AudioPlayer.ts index d58d8f962..805a1a918 100644 --- a/apps/common-app/src/examples/AudioFile/AudioPlayer.ts +++ b/apps/common-app/src/examples/AudioFile/AudioPlayer.ts @@ -73,8 +73,6 @@ class AudioPlayer { } }; - this.sourceNode.playbackRate.linearRampToValueAtTime(2, this.audioContext.currentTime + 5); - this.sourceNode.start( this.audioContext.currentTime, this.currentElapsedTime diff --git a/apps/fabric-example/ios/Podfile.lock b/apps/fabric-example/ios/Podfile.lock index 6389ddb14..613b233a4 100644 --- a/apps/fabric-example/ios/Podfile.lock +++ b/apps/fabric-example/ios/Podfile.lock @@ -2597,7 +2597,7 @@ SPEC CHECKSUMS: ReactCodegen: d07ee3c8db75b43d1cbe479ae6affebf9925c733 ReactCommon: fe2a3af8975e63efa60f95fca8c34dc85deee360 ReactNativeDependencies: 4d5ce2683b6d74f7c686bf90a88c7d381295cf3c - RNAudioAPI: 6bba1527c091e2702e3d879de7564ef1ccf30a78 + RNAudioAPI: 8a7e83b96d9be33bad7591400bb21c6e8b119222 RNAudioWorklets: febe470be646585d9b8b0de320a5fb8684cb012c RNGestureHandler: 187c5c7936abf427bc4d22d6c3b1ac80ad1f63c0 RNReanimated: 3a204af3747842859392545d41d443b9c5e428a3 diff --git a/packages/audiodocs/docs/other/disabling-prebuilt-libraries.mdx b/packages/audiodocs/docs/other/disabling-prebuilt-libraries.mdx index a3a87ed39..9a96ae731 100644 --- a/packages/audiodocs/docs/other/disabling-prebuilt-libraries.mdx +++ b/packages/audiodocs/docs/other/disabling-prebuilt-libraries.mdx @@ -17,7 +17,7 @@ The available flags are independent and can be combined: | Flag | What it removes | What stops working | | :---: | :---- | :---- | -| `disableFFmpeg` | FFmpeg shared libraries (`libavcodec`, `libavformat`, `libavutil`, `libswresample`) | Streaming, remote playback/metadata, `.aac` / `.mp4` / `.m4a` decode, M4A concat, **Android** non-WAV recording — see [Runtime flags](/docs/other/runtime-flags#where-ffmpeg-is-used) | +| `disableFFmpeg` | FFmpeg shared libraries (`libavcodec`, `libavformat`, `libavutil`, `libswresample`) | Remote URL streaming / HLS, remote URL metadata, M4A concat, **Android** non-WAV recording — see [Runtime flags](/docs/other/runtime-flags#where-ffmpeg-is-used) | | `disableStaticExternalLibs` | Static libs: `libopus`, `libopusfile`, `libogg`, `libvorbis`, `libvorbisenc`, `libvorbisfile` | Decoding `ogg`, `opus`, `oga` files | :::info diff --git a/packages/audiodocs/docs/other/runtime-flags.mdx b/packages/audiodocs/docs/other/runtime-flags.mdx index 7cbe0364b..6383a2418 100644 --- a/packages/audiodocs/docs/other/runtime-flags.mdx +++ b/packages/audiodocs/docs/other/runtime-flags.mdx @@ -29,16 +29,14 @@ if (!isFfmpegEnabled()) { | Area | API | Requires FFmpeg for | | :---: | :---: | :---- | -| Streaming | [`Audio tag`](/docs/sources/audio-tag) | HLS playback | -| Playback | `createFileSource`, [`