capacitor-voice-recorder-wav-stereo 7.0.9 → 8.0.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.
Files changed (31) hide show
  1. package/CapacitorVoiceRecorderWavStereo.podspec +17 -17
  2. package/README.md +213 -213
  3. package/android/build.gradle +80 -58
  4. package/android/src/main/AndroidManifest.xml +2 -2
  5. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/CurrentRecordingStatus.java +7 -7
  6. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/CustomMediaRecorder.java +186 -186
  7. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/Messages.java +15 -15
  8. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/NotSupportedOsVersion.java +4 -4
  9. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/RecordData.java +51 -51
  10. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/ResponseGenerator.java +37 -37
  11. package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/VoiceRecorder.java +217 -217
  12. package/dist/docs.json +1 -1
  13. package/dist/esm/VoiceRecorderImpl.js.map +1 -1
  14. package/dist/esm/definitions.js.map +1 -1
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/predefined-web-responses.js.map +1 -1
  17. package/dist/esm/web.js.map +1 -1
  18. package/dist/plugin.cjs.js +3 -3
  19. package/dist/plugin.cjs.js.map +1 -1
  20. package/dist/plugin.js +3 -3
  21. package/dist/plugin.js.map +1 -1
  22. package/ios/Plugin/CurrentRecordingStatus.swift +9 -9
  23. package/ios/Plugin/CustomMediaRecorder.swift +82 -82
  24. package/ios/Plugin/Info.plist +24 -24
  25. package/ios/Plugin/Messages.swift +15 -15
  26. package/ios/Plugin/RecordData.swift +17 -17
  27. package/ios/Plugin/ResponseGenerator.swift +28 -28
  28. package/ios/Plugin/VoiceRecorder.swift +179 -179
  29. package/ios/Plugin/VoiceRecorderPlugin.h +10 -10
  30. package/ios/Plugin/VoiceRecorderPlugin.m +16 -16
  31. package/package.json +92 -92
@@ -1,179 +1,179 @@
1
- import Foundation
2
- import AVFoundation
3
- import Capacitor
4
-
5
- @objc(VoiceRecorder)
6
- public class VoiceRecorder: CAPPlugin {
7
-
8
- private var customMediaRecorder: CustomMediaRecorder? = nil
9
-
10
- @objc func canDeviceVoiceRecord(_ call: CAPPluginCall) {
11
- call.resolve(ResponseGenerator.successResponse())
12
- }
13
-
14
- @objc func requestAudioRecordingPermission(_ call: CAPPluginCall) {
15
- AVAudioSession.sharedInstance().requestRecordPermission { granted in
16
- if granted {
17
- call.resolve(ResponseGenerator.successResponse())
18
- } else {
19
- call.resolve(ResponseGenerator.failResponse())
20
- }
21
- }
22
- }
23
-
24
- @objc func hasAudioRecordingPermission(_ call: CAPPluginCall) {
25
- call.resolve(ResponseGenerator.fromBoolean(doesUserGaveAudioRecordingPermission()))
26
- }
27
-
28
-
29
- @objc func startRecording(_ call: CAPPluginCall) {
30
- if(!doesUserGaveAudioRecordingPermission()) {
31
- call.reject(Messages.MISSING_PERMISSION)
32
- return
33
- }
34
-
35
- if(customMediaRecorder != nil) {
36
- call.reject(Messages.ALREADY_RECORDING)
37
- return
38
- }
39
-
40
- customMediaRecorder = CustomMediaRecorder()
41
- if(customMediaRecorder == nil) {
42
- call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
43
- return
44
- }
45
-
46
- let successfullyStartedRecording = customMediaRecorder!.startRecording()
47
- if successfullyStartedRecording == false {
48
- call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
49
- } else {
50
- call.resolve(ResponseGenerator.successResponse())
51
- }
52
- }
53
-
54
- @objc func stopRecording(_ call: CAPPluginCall) {
55
- if(customMediaRecorder == nil) {
56
- call.reject(Messages.RECORDING_HAS_NOT_STARTED)
57
- return
58
- }
59
-
60
- customMediaRecorder?.stopRecording()
61
-
62
- let audioFileUrl = customMediaRecorder?.getOutputFile()
63
- if(audioFileUrl == nil) {
64
- customMediaRecorder = nil
65
- call.reject(Messages.FAILED_TO_FETCH_RECORDING)
66
- return
67
- }
68
- let recordData = RecordData(
69
- recordDataBase64: readFileAsBase64(audioFileUrl),
70
- mimeType: "audio/aac",
71
- msDuration: getMsDurationOfAudioFile(audioFileUrl)
72
- )
73
- customMediaRecorder = nil
74
- if recordData.recordDataBase64 == nil || recordData.msDuration < 0 {
75
- call.reject(Messages.EMPTY_RECORDING)
76
- } else {
77
- call.resolve(ResponseGenerator.dataResponse(recordData.toDictionary()))
78
- }
79
- }
80
-
81
- @objc func pauseRecording(_ call: CAPPluginCall) {
82
- if(customMediaRecorder == nil) {
83
- call.reject(Messages.RECORDING_HAS_NOT_STARTED)
84
- } else {
85
- call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.pauseRecording() ?? false))
86
- }
87
- }
88
-
89
- @objc func resumeRecording(_ call: CAPPluginCall) {
90
- if(customMediaRecorder == nil) {
91
- call.reject(Messages.RECORDING_HAS_NOT_STARTED)
92
- } else {
93
- call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.resumeRecording() ?? false))
94
- }
95
- }
96
-
97
- @objc func getCurrentStatus(_ call: CAPPluginCall) {
98
- if(customMediaRecorder == nil) {
99
- call.resolve(ResponseGenerator.statusResponse(CurrentRecordingStatus.NONE))
100
- } else {
101
- call.resolve(ResponseGenerator.statusResponse(customMediaRecorder?.getCurrentStatus() ?? CurrentRecordingStatus.NONE))
102
- }
103
- }
104
-
105
- @objc func getConnectedDevices(_ call: CAPPluginCall) {
106
- let audioSession = AVAudioSession.sharedInstance()
107
- var devices = [[String: Any]]()
108
-
109
- // ロックを取得して状態変更を防ぐ
110
- objc_sync_enter(audioSession)
111
- defer { objc_sync_exit(audioSession) }
112
-
113
- do {
114
- // 現在のルートを強制保持
115
- let originalRoute = audioSession.currentRoute
116
- print("Original Route: \(originalRoute)")
117
-
118
- // カテゴリ変更を完全に排除
119
- let availableInputs = audioSession.availableInputs ?? []
120
- for port in availableInputs {
121
- devices.append([
122
- "deviceId": port.uid,
123
- "kind": "audioinput",
124
- "label": port.portName,
125
- "groupId": NSNull()
126
- ])
127
- }
128
-
129
- // 出力デバイスは現在のルートから取得(変更なし)
130
- for port in originalRoute.outputs {
131
- devices.append([
132
- "deviceId": port.uid,
133
- "kind": "audiooutput",
134
- "label": port.portName,
135
- "groupId": NSNull()
136
- ])
137
- }
138
-
139
- // ルート変更検知
140
- if audioSession.currentRoute != originalRoute {
141
- print("Route changed unexpectedly!")
142
- print("New Route: \(audioSession.currentRoute)")
143
- throw NSError(domain: "AudioSessionError", code: 1, userInfo: nil)
144
- }
145
-
146
- } catch {
147
- call.reject("Audio session conflict: \(error.localizedDescription)")
148
- return
149
- }
150
-
151
- call.resolve(["devices": devices])
152
- }
153
-
154
- func doesUserGaveAudioRecordingPermission() -> Bool {
155
- return AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted
156
- }
157
-
158
- func readFileAsBase64(_ filePath: URL?) -> String? {
159
- if(filePath == nil) {
160
- return nil
161
- }
162
-
163
- do {
164
- let fileData = try Data.init(contentsOf: filePath!)
165
- let fileStream = fileData.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))
166
- return fileStream
167
- } catch {}
168
-
169
- return nil
170
- }
171
-
172
- func getMsDurationOfAudioFile(_ filePath: URL?) -> Int {
173
- if filePath == nil {
174
- return -1
175
- }
176
- return Int(CMTimeGetSeconds(AVURLAsset(url: filePath!).duration) * 1000)
177
- }
178
-
179
- }
1
+ import Foundation
2
+ import AVFoundation
3
+ import Capacitor
4
+
5
+ @objc(VoiceRecorder)
6
+ public class VoiceRecorder: CAPPlugin {
7
+
8
+ private var customMediaRecorder: CustomMediaRecorder? = nil
9
+
10
+ @objc func canDeviceVoiceRecord(_ call: CAPPluginCall) {
11
+ call.resolve(ResponseGenerator.successResponse())
12
+ }
13
+
14
+ @objc func requestAudioRecordingPermission(_ call: CAPPluginCall) {
15
+ AVAudioSession.sharedInstance().requestRecordPermission { granted in
16
+ if granted {
17
+ call.resolve(ResponseGenerator.successResponse())
18
+ } else {
19
+ call.resolve(ResponseGenerator.failResponse())
20
+ }
21
+ }
22
+ }
23
+
24
+ @objc func hasAudioRecordingPermission(_ call: CAPPluginCall) {
25
+ call.resolve(ResponseGenerator.fromBoolean(doesUserGaveAudioRecordingPermission()))
26
+ }
27
+
28
+
29
+ @objc func startRecording(_ call: CAPPluginCall) {
30
+ if(!doesUserGaveAudioRecordingPermission()) {
31
+ call.reject(Messages.MISSING_PERMISSION)
32
+ return
33
+ }
34
+
35
+ if(customMediaRecorder != nil) {
36
+ call.reject(Messages.ALREADY_RECORDING)
37
+ return
38
+ }
39
+
40
+ customMediaRecorder = CustomMediaRecorder()
41
+ if(customMediaRecorder == nil) {
42
+ call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
43
+ return
44
+ }
45
+
46
+ let successfullyStartedRecording = customMediaRecorder!.startRecording()
47
+ if successfullyStartedRecording == false {
48
+ call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
49
+ } else {
50
+ call.resolve(ResponseGenerator.successResponse())
51
+ }
52
+ }
53
+
54
+ @objc func stopRecording(_ call: CAPPluginCall) {
55
+ if(customMediaRecorder == nil) {
56
+ call.reject(Messages.RECORDING_HAS_NOT_STARTED)
57
+ return
58
+ }
59
+
60
+ customMediaRecorder?.stopRecording()
61
+
62
+ let audioFileUrl = customMediaRecorder?.getOutputFile()
63
+ if(audioFileUrl == nil) {
64
+ customMediaRecorder = nil
65
+ call.reject(Messages.FAILED_TO_FETCH_RECORDING)
66
+ return
67
+ }
68
+ let recordData = RecordData(
69
+ recordDataBase64: readFileAsBase64(audioFileUrl),
70
+ mimeType: "audio/aac",
71
+ msDuration: getMsDurationOfAudioFile(audioFileUrl)
72
+ )
73
+ customMediaRecorder = nil
74
+ if recordData.recordDataBase64 == nil || recordData.msDuration < 0 {
75
+ call.reject(Messages.EMPTY_RECORDING)
76
+ } else {
77
+ call.resolve(ResponseGenerator.dataResponse(recordData.toDictionary()))
78
+ }
79
+ }
80
+
81
+ @objc func pauseRecording(_ call: CAPPluginCall) {
82
+ if(customMediaRecorder == nil) {
83
+ call.reject(Messages.RECORDING_HAS_NOT_STARTED)
84
+ } else {
85
+ call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.pauseRecording() ?? false))
86
+ }
87
+ }
88
+
89
+ @objc func resumeRecording(_ call: CAPPluginCall) {
90
+ if(customMediaRecorder == nil) {
91
+ call.reject(Messages.RECORDING_HAS_NOT_STARTED)
92
+ } else {
93
+ call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.resumeRecording() ?? false))
94
+ }
95
+ }
96
+
97
+ @objc func getCurrentStatus(_ call: CAPPluginCall) {
98
+ if(customMediaRecorder == nil) {
99
+ call.resolve(ResponseGenerator.statusResponse(CurrentRecordingStatus.NONE))
100
+ } else {
101
+ call.resolve(ResponseGenerator.statusResponse(customMediaRecorder?.getCurrentStatus() ?? CurrentRecordingStatus.NONE))
102
+ }
103
+ }
104
+
105
+ @objc func getConnectedDevices(_ call: CAPPluginCall) {
106
+ let audioSession = AVAudioSession.sharedInstance()
107
+ var devices = [[String: Any]]()
108
+
109
+ // ロックを取得して状態変更を防ぐ
110
+ objc_sync_enter(audioSession)
111
+ defer { objc_sync_exit(audioSession) }
112
+
113
+ do {
114
+ // 現在のルートを強制保持
115
+ let originalRoute = audioSession.currentRoute
116
+ print("Original Route: \(originalRoute)")
117
+
118
+ // カテゴリ変更を完全に排除
119
+ let availableInputs = audioSession.availableInputs ?? []
120
+ for port in availableInputs {
121
+ devices.append([
122
+ "deviceId": port.uid,
123
+ "kind": "audioinput",
124
+ "label": port.portName,
125
+ "groupId": NSNull()
126
+ ])
127
+ }
128
+
129
+ // 出力デバイスは現在のルートから取得(変更なし)
130
+ for port in originalRoute.outputs {
131
+ devices.append([
132
+ "deviceId": port.uid,
133
+ "kind": "audiooutput",
134
+ "label": port.portName,
135
+ "groupId": NSNull()
136
+ ])
137
+ }
138
+
139
+ // ルート変更検知
140
+ if audioSession.currentRoute != originalRoute {
141
+ print("Route changed unexpectedly!")
142
+ print("New Route: \(audioSession.currentRoute)")
143
+ throw NSError(domain: "AudioSessionError", code: 1, userInfo: nil)
144
+ }
145
+
146
+ } catch {
147
+ call.reject("Audio session conflict: \(error.localizedDescription)")
148
+ return
149
+ }
150
+
151
+ call.resolve(["devices": devices])
152
+ }
153
+
154
+ func doesUserGaveAudioRecordingPermission() -> Bool {
155
+ return AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted
156
+ }
157
+
158
+ func readFileAsBase64(_ filePath: URL?) -> String? {
159
+ if(filePath == nil) {
160
+ return nil
161
+ }
162
+
163
+ do {
164
+ let fileData = try Data.init(contentsOf: filePath!)
165
+ let fileStream = fileData.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))
166
+ return fileStream
167
+ } catch {}
168
+
169
+ return nil
170
+ }
171
+
172
+ func getMsDurationOfAudioFile(_ filePath: URL?) -> Int {
173
+ if filePath == nil {
174
+ return -1
175
+ }
176
+ return Int(CMTimeGetSeconds(AVURLAsset(url: filePath!).duration) * 1000)
177
+ }
178
+
179
+ }
@@ -1,10 +1,10 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- //! Project version number for Plugin.
4
- FOUNDATION_EXPORT double PluginVersionNumber;
5
-
6
- //! Project version string for Plugin.
7
- FOUNDATION_EXPORT const unsigned char PluginVersionString[];
8
-
9
- // In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
10
-
1
+ #import <UIKit/UIKit.h>
2
+
3
+ //! Project version number for Plugin.
4
+ FOUNDATION_EXPORT double PluginVersionNumber;
5
+
6
+ //! Project version string for Plugin.
7
+ FOUNDATION_EXPORT const unsigned char PluginVersionString[];
8
+
9
+ // In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
10
+
@@ -1,16 +1,16 @@
1
- #import <Foundation/Foundation.h>
2
- #import <Capacitor/Capacitor.h>
3
-
4
- // Define the plugin using the CAP_PLUGIN Macro, and
5
- // each method the plugin supports using the CAP_PLUGIN_METHOD macro.
6
- CAP_PLUGIN(VoiceRecorder, "VoiceRecorder",
7
- CAP_PLUGIN_METHOD(canDeviceVoiceRecord, CAPPluginReturnPromise);
8
- CAP_PLUGIN_METHOD(requestAudioRecordingPermission, CAPPluginReturnPromise);
9
- CAP_PLUGIN_METHOD(hasAudioRecordingPermission, CAPPluginReturnPromise);
10
- CAP_PLUGIN_METHOD(startRecording, CAPPluginReturnPromise);
11
- CAP_PLUGIN_METHOD(stopRecording, CAPPluginReturnPromise);
12
- CAP_PLUGIN_METHOD(pauseRecording, CAPPluginReturnPromise);
13
- CAP_PLUGIN_METHOD(resumeRecording, CAPPluginReturnPromise);
14
- CAP_PLUGIN_METHOD(getCurrentStatus, CAPPluginReturnPromise);
15
- CAP_PLUGIN_METHOD(getConnectedDevices, CAPPluginReturnPromise);
16
- )
1
+ #import <Foundation/Foundation.h>
2
+ #import <Capacitor/Capacitor.h>
3
+
4
+ // Define the plugin using the CAP_PLUGIN Macro, and
5
+ // each method the plugin supports using the CAP_PLUGIN_METHOD macro.
6
+ CAP_PLUGIN(VoiceRecorder, "VoiceRecorder",
7
+ CAP_PLUGIN_METHOD(canDeviceVoiceRecord, CAPPluginReturnPromise);
8
+ CAP_PLUGIN_METHOD(requestAudioRecordingPermission, CAPPluginReturnPromise);
9
+ CAP_PLUGIN_METHOD(hasAudioRecordingPermission, CAPPluginReturnPromise);
10
+ CAP_PLUGIN_METHOD(startRecording, CAPPluginReturnPromise);
11
+ CAP_PLUGIN_METHOD(stopRecording, CAPPluginReturnPromise);
12
+ CAP_PLUGIN_METHOD(pauseRecording, CAPPluginReturnPromise);
13
+ CAP_PLUGIN_METHOD(resumeRecording, CAPPluginReturnPromise);
14
+ CAP_PLUGIN_METHOD(getCurrentStatus, CAPPluginReturnPromise);
15
+ CAP_PLUGIN_METHOD(getConnectedDevices, CAPPluginReturnPromise);
16
+ )
package/package.json CHANGED
@@ -1,92 +1,92 @@
1
- {
2
- "name": "capacitor-voice-recorder-wav-stereo",
3
- "version": "7.0.9",
4
- "description": "Capacitor plugin for voice recording in wav format",
5
- "main": "dist/plugin.cjs.js",
6
- "module": "dist/esm/index.js",
7
- "types": "dist/esm/index.d.ts",
8
- "unpkg": "dist/plugin.js",
9
- "files": [
10
- "android/src/main/",
11
- "android/build.gradle",
12
- "dist/",
13
- "ios/Plugin/",
14
- "CapacitorVoiceRecorderWavStereo.podspec"
15
- ],
16
- "author": {
17
- "name": "Jun Murakami",
18
- "email": "jun.murakami.dev@gmail.com"
19
- },
20
- "license": "MIT",
21
- "repository": {
22
- "type": "git",
23
- "url": "git+https://github.com/Jun-Murakami/capacitor-voice-recorder-wav-stereo.git"
24
- },
25
- "bugs": {
26
- "url": "https://github.com/Jun-Murakami/capacitor-voice-recorder-wav-stereo/issues"
27
- },
28
- "keywords": [
29
- "capacitor",
30
- "plugin",
31
- "native",
32
- "voice",
33
- "audio",
34
- "record",
35
- "recorder",
36
- "ios",
37
- "android"
38
- ],
39
- "scripts": {
40
- "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
41
- "verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin -destination generic/platform=iOS && cd ..",
42
- "verify:android": "cd android && ./gradlew clean build test && cd ..",
43
- "verify:web": "npm run build",
44
- "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
45
- "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
46
- "eslint": "eslint . --ext ts",
47
- "prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
48
- "swiftlint": "node-swiftlint",
49
- "docgen": "docgen --api VoiceRecorderPlugin --output-readme README.md --output-json dist/docs.json",
50
- "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
51
- "clean": "rimraf ./dist",
52
- "watch": "tsc --watch",
53
- "prepublishOnly": "npm run build"
54
- },
55
- "dependencies": {
56
- "get-blob-duration": "^1.2.0"
57
- },
58
- "devDependencies": {
59
- "@capacitor/android": "^7.0.1",
60
- "@capacitor/cli": "^7.0.1",
61
- "@capacitor/core": "^7.0.1",
62
- "@capacitor/docgen": "^0.3.0",
63
- "@capacitor/ios": "^7.0.1",
64
- "@ionic/eslint-config": "^0.4.0",
65
- "@ionic/prettier-config": "^4.0.0",
66
- "@ionic/swiftlint-config": "^2.0.0",
67
- "@typescript-eslint/eslint-plugin": "^8.22.0",
68
- "eslint": "^9.19.0",
69
- "prettier": "~3.4.2",
70
- "prettier-plugin-java": "~2.6.7",
71
- "rimraf": "^6.0.1",
72
- "rollup": "^4.32.1",
73
- "swiftlint": "^2.0.0",
74
- "typescript": "5.7.3"
75
- },
76
- "peerDependencies": {
77
- "@capacitor/core": "^6.0.0"
78
- },
79
- "prettier": "@ionic/prettier-config",
80
- "swiftlint": "@ionic/swiftlint-config",
81
- "eslintConfig": {
82
- "extends": "@ionic/eslint-config/recommended"
83
- },
84
- "capacitor": {
85
- "ios": {
86
- "src": "ios"
87
- },
88
- "android": {
89
- "src": "android"
90
- }
91
- }
92
- }
1
+ {
2
+ "name": "capacitor-voice-recorder-wav-stereo",
3
+ "version": "8.0.0",
4
+ "description": "Capacitor plugin for voice recording in wav format",
5
+ "main": "dist/plugin.cjs.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/esm/index.d.ts",
8
+ "unpkg": "dist/plugin.js",
9
+ "files": [
10
+ "android/src/main/",
11
+ "android/build.gradle",
12
+ "dist/",
13
+ "ios/Plugin/",
14
+ "CapacitorVoiceRecorderWavStereo.podspec"
15
+ ],
16
+ "author": {
17
+ "name": "Jun Murakami",
18
+ "email": "jun.murakami.dev@gmail.com"
19
+ },
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/Jun-Murakami/capacitor-voice-recorder-wav-stereo.git"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/Jun-Murakami/capacitor-voice-recorder-wav-stereo/issues"
27
+ },
28
+ "keywords": [
29
+ "capacitor",
30
+ "plugin",
31
+ "native",
32
+ "voice",
33
+ "audio",
34
+ "record",
35
+ "recorder",
36
+ "ios",
37
+ "android"
38
+ ],
39
+ "scripts": {
40
+ "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
41
+ "verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin -destination generic/platform=iOS && cd ..",
42
+ "verify:android": "cd android && ./gradlew clean build test && cd ..",
43
+ "verify:web": "npm run build",
44
+ "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
45
+ "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
46
+ "eslint": "eslint . --ext ts",
47
+ "prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
48
+ "swiftlint": "node-swiftlint",
49
+ "docgen": "docgen --api VoiceRecorderPlugin --output-readme README.md --output-json dist/docs.json",
50
+ "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
51
+ "clean": "rimraf ./dist",
52
+ "watch": "tsc --watch",
53
+ "prepublishOnly": "npm run build"
54
+ },
55
+ "dependencies": {
56
+ "get-blob-duration": "^1.1.2"
57
+ },
58
+ "devDependencies": {
59
+ "@capacitor/android": "^8.0.2",
60
+ "@capacitor/cli": "^8.0.2",
61
+ "@capacitor/core": "^8.0.2",
62
+ "@capacitor/docgen": "^0.3.1",
63
+ "@capacitor/ios": "^8.0.2",
64
+ "@ionic/eslint-config": "^0.4.0",
65
+ "@ionic/prettier-config": "^4.0.0",
66
+ "@ionic/swiftlint-config": "^2.0.0",
67
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
68
+ "eslint": "^9.39.2",
69
+ "prettier": "^3.8.1",
70
+ "prettier-plugin-java": "^0.3.2",
71
+ "rimraf": "^6.1.2",
72
+ "rollup": "^4.57.1",
73
+ "swiftlint": "^2.0.0",
74
+ "typescript": "^5.9.3"
75
+ },
76
+ "peerDependencies": {
77
+ "@capacitor/core": ">=8.0.0"
78
+ },
79
+ "prettier": "@ionic/prettier-config",
80
+ "swiftlint": "@ionic/swiftlint-config",
81
+ "eslintConfig": {
82
+ "extends": "@ionic/eslint-config/recommended"
83
+ },
84
+ "capacitor": {
85
+ "ios": {
86
+ "src": "ios"
87
+ },
88
+ "android": {
89
+ "src": "android"
90
+ }
91
+ }
92
+ }