Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@

"Read(**)",

"WebFetch(https://webaudio.github.io/*)",
"WebFetch(https://developer.mozilla.org/*)",
"WebFetch(https://en.cppreference.com/*)",
"WebFetch(https://reactnative.dev/*)",
"WebFetch(domain:webaudio.github.io)",
"WebFetch(domain:developer.mozilla.org)",
"WebFetch(domain:en.cppreference.com)",
"WebFetch(domain:reactnative.dev)",
"WebSearch(*)",

"Write(.claude/**)",
Expand Down
4 changes: 3 additions & 1 deletion .claude/skills/build-compilation-dependencies/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/ # Decoder factory, backends, SeekDecoderDaemon, AudioDecoding, AudioFileConcatenator
│ │ ├── 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
Expand Down Expand Up @@ -268,7 +270,7 @@ CI runs a parallel `cpp-coverage` job via `.github/workflows/cpp-coverage-job.ym
### Key design decisions
- Completely standalone — no Gradle, no Xcode, no prebuilt Android libraries needed
- Sources resolved from `node_modules` (symlinked to `packages/` in yarn workspaces)
- HostObjects, worklets nodes, AudioContext, and FFmpegDecoding are excluded from the test build
- HostObjects, worklets nodes, AudioContext, and FfmpegDecoder are excluded from the test build
- Compile definitions: `RN_AUDIO_API_ENABLE_WORKLETS=0`, `RN_AUDIO_API_TEST=1`, `RN_AUDIO_API_FFMPEG_DISABLED=1`
- Google Test auto-fetched via `FetchContent` if not installed locally
- New test files in `test/src/**/*.cpp` are picked up automatically by glob — no CMakeLists edit needed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ file(GLOB_RECURSE COMMON_CPP_SOURCES CONFIGURE_DEPENDS "${COMMON_CPP_DIR}/audioa
```cmake
if(RN_AUDIO_API_FFMPEG_DISABLED)
list(REMOVE_ITEM COMMON_CPP_SOURCES
"${COMMON_CPP_DIR}/audioapi/libs/ffmpeg/FFmpegDecoding.cpp"
"${COMMON_CPP_DIR}/audioapi/decoding/backends/FfmpegDecoder.cpp"
)
endif()
```
Expand Down Expand Up @@ -262,7 +262,7 @@ This means **tests build against the installed/published version of the library*
list(FILTER RNAUDIOAPI_SRC EXCLUDE REGEX ".*/audioapi/HostObjects/.*\\.cpp$") # no JSI in tests
list(FILTER RNAUDIOAPI_SRC EXCLUDE REGEX ".*/Worklet.*Node\\.cpp$") # worklets not compiled
list(REMOVE_ITEM RNAUDIOAPI_SRC ... "AudioContext.cpp") # needs real audio I/O
list(REMOVE_ITEM RNAUDIOAPI_SRC ... "FFmpegDecoding.cpp") # FFmpeg disabled in tests
list(REMOVE_ITEM RNAUDIOAPI_SRC ... "FfmpegDecoder.cpp") # FFmpeg disabled in tests
```

### Compile definitions always set in tests
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/utilities/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ RAII mutex wrapper that can hold `nullptr` (no-op). Supports `Locker::tryLock(mu

### `AudioUtils.h` — inline DSP math

Provides `timeToSampleFrame()`, `sampleFrameToTime()`, `linearInterpolate()`, `linearToDecibels()`, `decibelsToLinear()`.
Provides `timeToSampleFrame()`, `sampleFrameToTime()`, `linearInterpolate()`, `linearToDecibels()`, `decibelsToLinear()`, `uint8ToFloat()` (LE int16 bytes → float).

For full API see [api.md](api.md#audioutilshpp--inline-dsp-math).

Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion THIRD_PARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Copyright (c) The WebKit Authors
In addition we utilize FFmpeg library under GNU Lesser General Public License (LGPL) version 2.1 or later

- Source: https://github.com/FFmpeg/FFmpeg/releases/tag/n8.0
- Used in audio decoding module [packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp](https://github.com/software-mansion/react-native-audio-api/blob/main/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp)
- Used in audio decoding module [packages/react-native-audio-api/common/cpp/audioapi/decoding/backends/FfmpegDecoder.cpp](https://github.com/software-mansion/react-native-audio-api/blob/main/packages/react-native-audio-api/common/cpp/audioapi/decoding/backends/FfmpegDecoder.cpp)
- Instruction for relinking: [packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/INSTRUCTIONS.md](https://github.com/software-mansion/react-native-audio-api/blob/main/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/INSTRUCTIONS.md)

Other LGPL components may be included as dependencies.
Expand Down
10 changes: 5 additions & 5 deletions apps/fabric-example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2523,7 +2523,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
FBLazyVector: c00c20551d40126351a6783c47ce75f5b374851b
hermes-engine: e97e6762d8c64a63b6e1d5cd704577fdd5992f9c
hermes-engine: 91023181d4bc5948b457de5314623fbfe4f8604e
RCTDeprecation: 3bb167081b134461cfeb875ff7ae1945f8635257
RCTRequired: 74839f55d5058a133a0bc4569b0afec750957f64
RCTSwiftUI: 87a316382f3eab4dd13d2a0d0fd2adcce917361a
Expand All @@ -2532,7 +2532,7 @@ SPEC CHECKSUMS:
React: 1b1536b9099195944034e65b1830f463caaa8390
React-callinvoker: 6dff6d17d1d6cc8fdf85468a649bafed473c65f5
React-Core: 00faa4d038298089a1d5a5b21dde8660c4f0820d
React-Core-prebuilt: c28e62d9521adb5940a1bf6d8d31c4f70debdbe3
React-Core-prebuilt: a6d614de037caff7898424dfc22915ec792de921
React-CoreModules: a17807f849bfd86045b0b9a75ec8c19373b482f6
React-cxxreact: c7b53ace5827be54048288bce5c55f337c41e95f
React-debug: e1f00fcd2cef58a2897471a6d76a4ef5f5f90c74
Expand Down Expand Up @@ -2596,9 +2596,9 @@ SPEC CHECKSUMS:
ReactAppDependencyProvider: 5787b37b8e2e51dfeab697ec031cc7c4080dcea2
ReactCodegen: d07ee3c8db75b43d1cbe479ae6affebf9925c733
ReactCommon: fe2a3af8975e63efa60f95fca8c34dc85deee360
ReactNativeDependencies: d78bc47c9d51cd25ac809534164aec0d5dcf46e9
RNAudioAPI: bf5a0c9caaa6d553c5aaa4e0b024596dea4634f7
RNAudioWorklets: febe470be646585d9b8b0de320a5fb8684cb012c
ReactNativeDependencies: 4d5ce2683b6d74f7c686bf90a88c7d381295cf3c
RNAudioAPI: 50957b72cc742b9aa1e05349be71b9db73c9cf74
RNAudioWorklets: ff0c53fd3c3bbffacb7dd3beb03ffe0ea9f1fd05
RNGestureHandler: 187c5c7936abf427bc4d22d6c3b1ac80ad1f63c0
RNReanimated: 3a204af3747842859392545d41d443b9c5e428a3
RNScreens: 01b065ded2dfe7987bcce770ff3a196be417ff41
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 3 additions & 5 deletions packages/audiodocs/docs/other/runtime-flags.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,14 @@ if (!isFfmpegEnabled()) {

| Area | API | Requires FFmpeg for |
| :---: | :---: | :---- |
| Streaming | [`Audio tag`](/docs/sources/audio-tag) | HLS playback |
| Playback | `createFileSource`, [`<Audio>`](/docs/sources/audio-tag) | Remote URL streaming, HLS (`.m3u8`), local `.mp4` / `.m4a` / `.aac`. Without FFmpeg, remote sources are downloaded and decoded with miniaudio where supported. |
| Decoding | [`decodeAudioData`](/docs/utils/decoding#decodeaudiodata) | `.aac`, `.mp4`, `.m4a` (and remote URLs for any format) |
| Streaming | [`Audio tag`](/docs/sources/audio-tag), `createFileSource` | Remote URL streaming (HTTP byte ranges) and HLS (`.m3u8`) |
| Metadata | [`getAudioDuration`](/docs/utils/decoding#getaudioduration), [`<Audio>`](/docs/sources/audio-tag) `preload="metadata"` | Remote `http(s):` URL duration probing |
| Recording | [`AudioRecorder`](/docs/inputs/audio-recorder) file output | **Android only:** `M4A`, `FLAC`, and `CAF` (WAV uses miniaudio). iOS uses system AVFoundation instead. |
| File utils | [`concatAudioFiles`](/docs/utils/file-concatenation#concataudiofiles) | M4A concatenation (WAV uses miniaudio) |

Formats such as `.mp3`, `.wav`, and `.flac` are often handled by miniaudio for **local** decode paths and for **downloaded** remote sources when FFmpeg is disabled.
Batch decoding ([`decodeAudioData`](/docs/utils/decoding#decodeaudiodata)) uses OS APIs on mobile (and miniaudio for formats like Ogg/Opus) — not FFmpeg. Without FFmpeg, remote progressive sources can still be fully downloaded in JS and decoded that way; HLS and in-place URL streaming remain unavailable.

When `isFfmpegEnabled()` returns `false`, the features in the table above are unavailable or fall back to errors. On **Android**, [`AudioRecorder`](/docs/inputs/audio-recorder) file output is limited to **WAV**.
When `isFfmpegEnabled()` returns `false`, the streaming/metadata features in the table above are unavailable or fall back to errors. On **Android**, [`AudioRecorder`](/docs/inputs/audio-recorder) file output is limited to **WAV**.

### Disabling FFmpeg

Expand Down
2 changes: 1 addition & 1 deletion packages/audiodocs/docs/sources/audio-tag.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,4 @@ const MyAudioTagWrapper : React.FC = () => {

## Remarks

- **FFmpeg:** HLS and several compressed formats require an FFmpeg build for URL streaming. Without FFmpeg, remote sources are downloaded and decoded with miniaudio where supported. See [Runtime flags](/docs/other/runtime-flags#where-ffmpeg-is-used).
- **FFmpeg:** Remote URL streaming (HTTP byte ranges) and HLS require an FFmpeg build. Without FFmpeg, remote progressive sources are downloaded fully and decoded with OS APIs / miniaudio where supported. See [Runtime flags](/docs/other/runtime-flags#where-ffmpeg-is-used).
5 changes: 3 additions & 2 deletions packages/audiodocs/docs/utils/decoding.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ Supported file formats:
- aac
- m4a
- mp4

On mobile, `.aac`, `.mp4`, and `.m4a` are decoded with FFmpeg — see [Runtime flags](/docs/other/runtime-flags#where-ffmpeg-is-used) for more info.
- aif
- aiff
- caf (ios)
:::

## Methods
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-audio-api/RNAudioAPI.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Pod::Spec.new do |s|

s.subspec "audioapi" do |ss|
ss.source_files = "common/cpp/audioapi/**/*.{cpp,c,h,hpp}"
ss.exclude_files = $RN_AUDIO_API_FFMPEG_DISABLED ? ["common/cpp/audioapi/libs/ffmpeg/**"] : []
ss.exclude_files = $RN_AUDIO_API_FFMPEG_DISABLED ? ["common/cpp/audioapi/decoding/backends/FfmpegDecoder.cpp"] : []
ss.header_dir = "audioapi"
ss.header_mappings_dir = "common/cpp/audioapi"

Expand All @@ -56,7 +56,7 @@ Pod::Spec.new do |s|
end
end

s.ios.frameworks = 'Accelerate', 'AVFoundation', 'MediaPlayer'
s.ios.frameworks = 'Accelerate', 'AVFoundation', 'AudioToolbox', 'MediaPlayer'

s.prepare_command = <<-CMD
chmod +x scripts/download-prebuilt-binaries.sh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ endforeach()

if (RN_AUDIO_API_FFMPEG_DISABLED)
list(REMOVE_ITEM COMMON_CPP_SOURCES
"${COMMON_CPP_DIR}/audioapi/libs/ffmpeg/FFmpegDecoding.cpp"
"${COMMON_CPP_DIR}/audioapi/decoding/backends/FfmpegDecoder.cpp"
)
endif()

Expand Down Expand Up @@ -105,6 +105,7 @@ set(LINK_LIBRARIES
fbjni::fbjni
android
log
mediandk
oboe::oboe
)

Expand Down
Loading
Loading