react-native-audio-concat 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AudioConcat.podspec +2 -21
- package/README.md +3 -7
- package/android/build.gradle +2 -54
- package/android/src/main/java/com/audioconcat/AudioConcatModule.kt +1178 -0
- package/android/src/main/java/com/audioconcat/AudioConcatPackage.kt +33 -0
- package/ios/AudioConcat.h +5 -0
- package/ios/AudioConcat.mm +104 -0
- package/lib/module/NativeAudioConcat.js +5 -0
- package/lib/module/NativeAudioConcat.js.map +1 -0
- package/lib/module/index.js +2 -28
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeAudioConcat.d.ts +12 -0
- package/lib/typescript/src/NativeAudioConcat.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -27
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +14 -18
- package/src/NativeAudioConcat.ts +12 -0
- package/src/index.tsx +4 -32
- package/android/CMakeLists.txt +0 -24
- package/android/src/main/cpp/cpp-adapter.cpp +0 -6
- package/android/src/main/java/com/margelo/nitro/audioconcat/AudioConcat.kt +0 -349
- package/android/src/main/java/com/margelo/nitro/audioconcat/AudioConcatPackage.kt +0 -22
- package/ios/AudioConcat.swift +0 -75
- package/lib/module/AudioConcat.nitro.js +0 -4
- package/lib/module/AudioConcat.nitro.js.map +0 -1
- package/lib/typescript/src/AudioConcat.nitro.d.ts +0 -16
- package/lib/typescript/src/AudioConcat.nitro.d.ts.map +0 -1
- package/nitro.json +0 -17
- package/nitrogen/generated/android/audioconcat+autolinking.cmake +0 -82
- package/nitrogen/generated/android/audioconcat+autolinking.gradle +0 -27
- package/nitrogen/generated/android/audioconcatOnLoad.cpp +0 -44
- package/nitrogen/generated/android/audioconcatOnLoad.hpp +0 -25
- package/nitrogen/generated/android/c++/JAudioData.hpp +0 -53
- package/nitrogen/generated/android/c++/JAudioDataOrSilence.cpp +0 -26
- package/nitrogen/generated/android/c++/JAudioDataOrSilence.hpp +0 -72
- package/nitrogen/generated/android/c++/JHybridAudioConcatSpec.cpp +0 -77
- package/nitrogen/generated/android/c++/JHybridAudioConcatSpec.hpp +0 -64
- package/nitrogen/generated/android/c++/JSilentData.hpp +0 -53
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audioconcat/AudioData.kt +0 -29
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audioconcat/AudioDataOrSilence.kt +0 -42
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audioconcat/HybridAudioConcatSpec.kt +0 -52
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audioconcat/SilentData.kt +0 -29
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audioconcat/audioconcatOnLoad.kt +0 -35
- package/nitrogen/generated/ios/AudioConcat+autolinking.rb +0 -60
- package/nitrogen/generated/ios/AudioConcat-Swift-Cxx-Bridge.cpp +0 -48
- package/nitrogen/generated/ios/AudioConcat-Swift-Cxx-Bridge.hpp +0 -160
- package/nitrogen/generated/ios/AudioConcat-Swift-Cxx-Umbrella.hpp +0 -53
- package/nitrogen/generated/ios/AudioConcatAutolinking.mm +0 -33
- package/nitrogen/generated/ios/AudioConcatAutolinking.swift +0 -25
- package/nitrogen/generated/ios/c++/HybridAudioConcatSpecSwift.cpp +0 -11
- package/nitrogen/generated/ios/c++/HybridAudioConcatSpecSwift.hpp +0 -81
- package/nitrogen/generated/ios/swift/AudioData.swift +0 -35
- package/nitrogen/generated/ios/swift/AudioDataOrSilence.swift +0 -18
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +0 -47
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +0 -47
- package/nitrogen/generated/ios/swift/HybridAudioConcatSpec.swift +0 -49
- package/nitrogen/generated/ios/swift/HybridAudioConcatSpec_cxx.swift +0 -142
- package/nitrogen/generated/ios/swift/SilentData.swift +0 -35
- package/nitrogen/generated/shared/c++/AudioData.hpp +0 -67
- package/nitrogen/generated/shared/c++/HybridAudioConcatSpec.cpp +0 -21
- package/nitrogen/generated/shared/c++/HybridAudioConcatSpec.hpp +0 -70
- package/nitrogen/generated/shared/c++/SilentData.hpp +0 -67
- package/src/AudioConcat.nitro.ts +0 -19
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.audioconcat
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import java.util.HashMap
|
|
9
|
+
|
|
10
|
+
class AudioConcatPackage : BaseReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == AudioConcatModule.NAME) {
|
|
13
|
+
AudioConcatModule(reactContext)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
20
|
+
return ReactModuleInfoProvider {
|
|
21
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
22
|
+
moduleInfos[AudioConcatModule.NAME] = ReactModuleInfo(
|
|
23
|
+
AudioConcatModule.NAME,
|
|
24
|
+
AudioConcatModule.NAME,
|
|
25
|
+
false, // canOverrideExistingModule
|
|
26
|
+
false, // needsEagerInit
|
|
27
|
+
false, // isCxxModule
|
|
28
|
+
true // isTurboModule
|
|
29
|
+
)
|
|
30
|
+
moduleInfos
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#import "AudioConcat.h"
|
|
2
|
+
#import <AVFoundation/AVFoundation.h>
|
|
3
|
+
|
|
4
|
+
@implementation AudioConcat
|
|
5
|
+
|
|
6
|
+
- (void)concatAudioFiles:(NSArray *)data
|
|
7
|
+
outputPath:(NSString *)outputPath
|
|
8
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
10
|
+
{
|
|
11
|
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
12
|
+
@try {
|
|
13
|
+
AVMutableComposition *composition = [AVMutableComposition composition];
|
|
14
|
+
AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio
|
|
15
|
+
preferredTrackID:kCMPersistentTrackID_Invalid];
|
|
16
|
+
|
|
17
|
+
CMTime currentTime = kCMTimeZero;
|
|
18
|
+
|
|
19
|
+
for (NSDictionary *item in data) {
|
|
20
|
+
if (item[@"filePath"]) {
|
|
21
|
+
// Add audio file
|
|
22
|
+
NSString *filePath = item[@"filePath"];
|
|
23
|
+
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
|
|
24
|
+
|
|
25
|
+
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
|
|
26
|
+
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeAudio];
|
|
27
|
+
|
|
28
|
+
if (tracks.count == 0) {
|
|
29
|
+
reject(@"ERR_NO_AUDIO_TRACK", [NSString stringWithFormat:@"No audio track found in file: %@", filePath], nil);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
AVAssetTrack *track = tracks[0];
|
|
34
|
+
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
|
|
35
|
+
|
|
36
|
+
NSError *error = nil;
|
|
37
|
+
[audioTrack insertTimeRange:timeRange
|
|
38
|
+
ofTrack:track
|
|
39
|
+
atTime:currentTime
|
|
40
|
+
error:&error];
|
|
41
|
+
|
|
42
|
+
if (error) {
|
|
43
|
+
reject(@"ERR_INSERT_TRACK", error.localizedDescription, error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
currentTime = CMTimeAdd(currentTime, asset.duration);
|
|
48
|
+
|
|
49
|
+
} else if (item[@"durationMs"]) {
|
|
50
|
+
// Add silence period
|
|
51
|
+
NSNumber *durationMs = item[@"durationMs"];
|
|
52
|
+
double durationSeconds = [durationMs doubleValue] / 1000.0;
|
|
53
|
+
CMTime silenceDuration = CMTimeMakeWithSeconds(durationSeconds, 600);
|
|
54
|
+
|
|
55
|
+
currentTime = CMTimeAdd(currentTime, silenceDuration);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Export the composition
|
|
60
|
+
NSURL *outputURL = [NSURL fileURLWithPath:outputPath];
|
|
61
|
+
|
|
62
|
+
// Remove existing file if it exists
|
|
63
|
+
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
|
|
64
|
+
|
|
65
|
+
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition
|
|
66
|
+
presetName:AVAssetExportPresetAppleM4A];
|
|
67
|
+
exportSession.outputURL = outputURL;
|
|
68
|
+
exportSession.outputFileType = AVFileTypeAppleM4A;
|
|
69
|
+
|
|
70
|
+
[exportSession exportAsynchronouslyWithCompletionHandler:^{
|
|
71
|
+
switch (exportSession.status) {
|
|
72
|
+
case AVAssetExportSessionStatusCompleted:
|
|
73
|
+
resolve(outputPath);
|
|
74
|
+
break;
|
|
75
|
+
case AVAssetExportSessionStatusFailed:
|
|
76
|
+
reject(@"ERR_EXPORT_FAILED", exportSession.error.localizedDescription, exportSession.error);
|
|
77
|
+
break;
|
|
78
|
+
case AVAssetExportSessionStatusCancelled:
|
|
79
|
+
reject(@"ERR_EXPORT_CANCELLED", @"Export was cancelled", nil);
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
reject(@"ERR_EXPORT_UNKNOWN", @"Unknown export error", nil);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}];
|
|
86
|
+
|
|
87
|
+
} @catch (NSException *exception) {
|
|
88
|
+
reject(@"ERR_EXCEPTION", exception.reason, nil);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
94
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
95
|
+
{
|
|
96
|
+
return std::make_shared<facebook::react::NativeAudioConcatSpecJSI>(params);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
+ (NSString *)moduleName
|
|
100
|
+
{
|
|
101
|
+
return @"AudioConcat";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeAudioConcat.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAWpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,aAAa,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,33 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
const AudioConcatHybridObject = NitroModules.createHybridObject('AudioConcat');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Concat audio files and silence periods into a single output file.
|
|
8
|
-
*
|
|
9
|
-
* @param data - Array of audio files and silence periods to merge.
|
|
10
|
-
* Each item can be either:
|
|
11
|
-
* - `{ filePath: string }` for an audio file
|
|
12
|
-
* - `{ durationMs: number }` for a silence period
|
|
13
|
-
* @param outputPath - Absolute path where the merged audio file will be saved (M4A format)
|
|
14
|
-
* @returns Promise that resolves with the output file path
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* const data = [
|
|
19
|
-
* { filePath: '/path/to/audio1.m4a' },
|
|
20
|
-
* { durationMs: 500 }, // 500ms silence
|
|
21
|
-
* { filePath: '/path/to/audio2.m4a' },
|
|
22
|
-
* { durationMs: 1000 }, // 1 second silence
|
|
23
|
-
* { filePath: '/path/to/audio3.m4a' }
|
|
24
|
-
* ];
|
|
25
|
-
* const output = '/path/to/merged.m4a';
|
|
26
|
-
* const result = await concatAudioFiles(data, output);
|
|
27
|
-
* console.log('concat file:', result);
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
3
|
+
import AudioConcat from "./NativeAudioConcat.js";
|
|
30
4
|
export function concatAudioFiles(data, outputPath) {
|
|
31
|
-
return
|
|
5
|
+
return AudioConcat.concatAudioFiles(data, outputPath);
|
|
32
6
|
}
|
|
33
7
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["AudioConcat","concatAudioFiles","data","outputPath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,WAAW,MAAM,wBAAqB;AAI7C,OAAO,SAASC,gBAAgBA,CAC9BC,IAA0D,EAC1DC,UAAkB,EACD;EACjB,OAAOH,WAAW,CAACC,gBAAgB,CAACC,IAAI,EAAEC,UAAU,CAAC;AACvD","ignoreList":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type TurboModule } from 'react-native';
|
|
2
|
+
export type AudioDataOrSilence = {
|
|
3
|
+
filePath: string;
|
|
4
|
+
} | {
|
|
5
|
+
durationMs: number;
|
|
6
|
+
};
|
|
7
|
+
export interface Spec extends TurboModule {
|
|
8
|
+
concatAudioFiles(data: AudioDataOrSilence[], outputPath: string): Promise<string>;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: Spec;
|
|
11
|
+
export default _default;
|
|
12
|
+
//# sourceMappingURL=NativeAudioConcat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeAudioConcat.d.ts","sourceRoot":"","sources":["../../../src/NativeAudioConcat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,gBAAgB,CACd,IAAI,EAAE,kBAAkB,EAAE,EAC1B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;;AAED,wBAAqE"}
|
|
@@ -1,28 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* - `{ filePath: string }` for an audio file
|
|
8
|
-
* - `{ durationMs: number }` for a silence period
|
|
9
|
-
* @param outputPath - Absolute path where the merged audio file will be saved (M4A format)
|
|
10
|
-
* @returns Promise that resolves with the output file path
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* const data = [
|
|
15
|
-
* { filePath: '/path/to/audio1.m4a' },
|
|
16
|
-
* { durationMs: 500 }, // 500ms silence
|
|
17
|
-
* { filePath: '/path/to/audio2.m4a' },
|
|
18
|
-
* { durationMs: 1000 }, // 1 second silence
|
|
19
|
-
* { filePath: '/path/to/audio3.m4a' }
|
|
20
|
-
* ];
|
|
21
|
-
* const output = '/path/to/merged.m4a';
|
|
22
|
-
* const result = await concatAudioFiles(data, output);
|
|
23
|
-
* console.log('concat file:', result);
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export declare function concatAudioFiles(data: AudioDataOrSilence[], outputPath: string): Promise<string>;
|
|
27
|
-
export type { AudioDataOrSilence } from './AudioConcat.nitro';
|
|
1
|
+
export type { AudioDataOrSilence } from './NativeAudioConcat';
|
|
2
|
+
export declare function concatAudioFiles(data: Array<{
|
|
3
|
+
filePath: string;
|
|
4
|
+
} | {
|
|
5
|
+
durationMs: number;
|
|
6
|
+
}>, outputPath: string): Promise<string>;
|
|
28
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1D,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAEjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audio-concat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "audio-concat for react-native",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
"android",
|
|
19
19
|
"ios",
|
|
20
20
|
"cpp",
|
|
21
|
-
"nitrogen",
|
|
22
|
-
"nitro.json",
|
|
23
21
|
"*.podspec",
|
|
24
22
|
"react-native.config.js",
|
|
25
23
|
"!ios/build",
|
|
@@ -40,8 +38,7 @@
|
|
|
40
38
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
41
39
|
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
42
40
|
"prepare": "bob build",
|
|
43
|
-
"release": "release-it --only-version"
|
|
44
|
-
"nitrogen": "nitrogen"
|
|
41
|
+
"release": "release-it --only-version"
|
|
45
42
|
},
|
|
46
43
|
"keywords": [
|
|
47
44
|
"react-native",
|
|
@@ -67,6 +64,7 @@
|
|
|
67
64
|
"@eslint/eslintrc": "^3.3.1",
|
|
68
65
|
"@eslint/js": "^9.35.0",
|
|
69
66
|
"@evilmartians/lefthook": "^1.12.3",
|
|
67
|
+
"@react-native-community/cli": "20.0.1",
|
|
70
68
|
"@react-native/babel-preset": "0.81.1",
|
|
71
69
|
"@react-native/eslint-config": "^0.81.1",
|
|
72
70
|
"@release-it/conventional-changelog": "^10.0.1",
|
|
@@ -78,20 +76,17 @@
|
|
|
78
76
|
"eslint-config-prettier": "^10.1.8",
|
|
79
77
|
"eslint-plugin-prettier": "^5.5.4",
|
|
80
78
|
"jest": "^29.7.0",
|
|
81
|
-
"nitrogen": "^0.29.8",
|
|
82
79
|
"prettier": "^3.6.2",
|
|
83
80
|
"react": "19.1.0",
|
|
84
81
|
"react-native": "0.81.1",
|
|
85
82
|
"react-native-builder-bob": "^0.40.13",
|
|
86
|
-
"react-native-nitro-modules": "^0.29.8",
|
|
87
83
|
"release-it": "^19.0.4",
|
|
88
84
|
"turbo": "^2.5.6",
|
|
89
85
|
"typescript": "^5.9.2"
|
|
90
86
|
},
|
|
91
87
|
"peerDependencies": {
|
|
92
88
|
"react": "*",
|
|
93
|
-
"react-native": "*"
|
|
94
|
-
"react-native-nitro-modules": "^0.29.8"
|
|
89
|
+
"react-native": "*"
|
|
95
90
|
},
|
|
96
91
|
"workspaces": [
|
|
97
92
|
"example"
|
|
@@ -139,13 +134,6 @@
|
|
|
139
134
|
"source": "src",
|
|
140
135
|
"output": "lib",
|
|
141
136
|
"targets": [
|
|
142
|
-
[
|
|
143
|
-
"custom",
|
|
144
|
-
{
|
|
145
|
-
"script": "nitrogen",
|
|
146
|
-
"clean": "nitrogen/"
|
|
147
|
-
}
|
|
148
|
-
],
|
|
149
137
|
[
|
|
150
138
|
"module",
|
|
151
139
|
{
|
|
@@ -160,9 +148,17 @@
|
|
|
160
148
|
]
|
|
161
149
|
]
|
|
162
150
|
},
|
|
151
|
+
"codegenConfig": {
|
|
152
|
+
"name": "AudioConcatSpec",
|
|
153
|
+
"type": "modules",
|
|
154
|
+
"jsSrcsDir": "src",
|
|
155
|
+
"android": {
|
|
156
|
+
"javaPackageName": "com.audioconcat"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
163
159
|
"create-react-native-library": {
|
|
164
|
-
"languages": "kotlin-
|
|
165
|
-
"type": "
|
|
160
|
+
"languages": "kotlin-objc",
|
|
161
|
+
"type": "turbo-module",
|
|
166
162
|
"version": "0.54.5"
|
|
167
163
|
}
|
|
168
164
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type AudioDataOrSilence = { filePath: string } | { durationMs: number };
|
|
4
|
+
|
|
5
|
+
export interface Spec extends TurboModule {
|
|
6
|
+
concatAudioFiles(
|
|
7
|
+
data: AudioDataOrSilence[],
|
|
8
|
+
outputPath: string
|
|
9
|
+
): Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('AudioConcat');
|
package/src/index.tsx
CHANGED
|
@@ -1,38 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { AudioConcat, AudioDataOrSilence } from './AudioConcat.nitro';
|
|
1
|
+
import AudioConcat from './NativeAudioConcat';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
NitroModules.createHybridObject<AudioConcat>('AudioConcat');
|
|
3
|
+
export type { AudioDataOrSilence } from './NativeAudioConcat';
|
|
6
4
|
|
|
7
|
-
/**
|
|
8
|
-
* Concat audio files and silence periods into a single output file.
|
|
9
|
-
*
|
|
10
|
-
* @param data - Array of audio files and silence periods to merge.
|
|
11
|
-
* Each item can be either:
|
|
12
|
-
* - `{ filePath: string }` for an audio file
|
|
13
|
-
* - `{ durationMs: number }` for a silence period
|
|
14
|
-
* @param outputPath - Absolute path where the merged audio file will be saved (M4A format)
|
|
15
|
-
* @returns Promise that resolves with the output file path
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* const data = [
|
|
20
|
-
* { filePath: '/path/to/audio1.m4a' },
|
|
21
|
-
* { durationMs: 500 }, // 500ms silence
|
|
22
|
-
* { filePath: '/path/to/audio2.m4a' },
|
|
23
|
-
* { durationMs: 1000 }, // 1 second silence
|
|
24
|
-
* { filePath: '/path/to/audio3.m4a' }
|
|
25
|
-
* ];
|
|
26
|
-
* const output = '/path/to/merged.m4a';
|
|
27
|
-
* const result = await concatAudioFiles(data, output);
|
|
28
|
-
* console.log('concat file:', result);
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
5
|
export function concatAudioFiles(
|
|
32
|
-
data:
|
|
6
|
+
data: Array<{ filePath: string } | { durationMs: number }>,
|
|
33
7
|
outputPath: string
|
|
34
8
|
): Promise<string> {
|
|
35
|
-
return
|
|
9
|
+
return AudioConcat.concatAudioFiles(data, outputPath);
|
|
36
10
|
}
|
|
37
|
-
|
|
38
|
-
export type { AudioDataOrSilence } from './AudioConcat.nitro';
|
package/android/CMakeLists.txt
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
project(audioconcat)
|
|
2
|
-
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
-
|
|
4
|
-
set(PACKAGE_NAME audioconcat)
|
|
5
|
-
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
-
set(CMAKE_CXX_STANDARD 20)
|
|
7
|
-
|
|
8
|
-
# Define C++ library and add all sources
|
|
9
|
-
add_library(${PACKAGE_NAME} SHARED src/main/cpp/cpp-adapter.cpp)
|
|
10
|
-
|
|
11
|
-
# Add Nitrogen specs :)
|
|
12
|
-
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/audioconcat+autolinking.cmake)
|
|
13
|
-
|
|
14
|
-
# Set up local includes
|
|
15
|
-
include_directories("src/main/cpp" "../cpp")
|
|
16
|
-
|
|
17
|
-
find_library(LOG_LIB log)
|
|
18
|
-
|
|
19
|
-
# Link all libraries together
|
|
20
|
-
target_link_libraries(
|
|
21
|
-
${PACKAGE_NAME}
|
|
22
|
-
${LOG_LIB}
|
|
23
|
-
android # <-- Android core
|
|
24
|
-
)
|