@capgo/capacitor-screen-recorder 1.2.5 → 1.2.10
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/CapgoCapacitorScreenRecorder.podspec +1 -1
- package/README.md +5 -0
- package/android/build.gradle +8 -8
- package/android/src/main/java/ee/forgr/plugin/screenrecorder/ScreenRecorderPlugin.java +2 -2
- package/dist/docs.json +3 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.js +2 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +3 -5
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +3 -5
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/Wyler.swift +161 -161
- package/package.json +18 -13
|
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
|
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
13
|
s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
-
s.ios.deployment_target = '
|
|
14
|
+
s.ios.deployment_target = '13.0'
|
|
15
15
|
s.dependency 'Capacitor'
|
|
16
16
|
s.swift_version = '5.1'
|
|
17
17
|
end
|
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# capacitor-screen-recorder
|
|
2
2
|
<a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
|
|
3
|
+
|
|
4
|
+
<div align="center">
|
|
5
|
+
<h2><a href="https://capgo.app/">Check out: Capgo — Instant updates for capacitor</a></h2>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
3
8
|
Record device's screen
|
|
4
9
|
|
|
5
10
|
## Install
|
package/android/build.gradle
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
ext {
|
|
2
|
-
junitVersion =
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.3'
|
|
4
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.4.0'
|
|
3
5
|
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.3.2'
|
|
4
6
|
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.2.0'
|
|
5
|
-
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.2'
|
|
6
|
-
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.3.0'
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
buildscript {
|
|
@@ -13,7 +13,7 @@ buildscript {
|
|
|
13
13
|
jcenter()
|
|
14
14
|
}
|
|
15
15
|
dependencies {
|
|
16
|
-
classpath 'com.android.tools.build:gradle:
|
|
16
|
+
classpath 'com.android.tools.build:gradle:7.2.1'
|
|
17
17
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -22,10 +22,10 @@ apply plugin: 'com.android.library'
|
|
|
22
22
|
apply plugin: 'kotlin-android'
|
|
23
23
|
|
|
24
24
|
android {
|
|
25
|
-
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion :
|
|
25
|
+
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 32
|
|
26
26
|
defaultConfig {
|
|
27
|
-
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion :
|
|
28
|
-
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion :
|
|
27
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
28
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 32
|
|
29
29
|
versionCode 1
|
|
30
30
|
versionName "1.0"
|
|
31
31
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
@@ -14,7 +14,7 @@ public class ScreenRecorderPlugin extends Plugin {
|
|
|
14
14
|
|
|
15
15
|
@Override
|
|
16
16
|
public void load() {
|
|
17
|
-
recorder =
|
|
17
|
+
recorder = ScrCast.use(this.bridge.getActivity());
|
|
18
18
|
Options options = new Options();
|
|
19
19
|
recorder.updateOptions(options);
|
|
20
20
|
}
|
|
@@ -24,7 +24,7 @@ public class ScreenRecorderPlugin extends Plugin {
|
|
|
24
24
|
recorder.record();
|
|
25
25
|
call.resolve();
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
@PluginMethod
|
|
29
29
|
public void stop(PluginCall call) {
|
|
30
30
|
recorder.stopRecording();
|
package/dist/docs.json
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { registerPlugin } from '@capacitor/core';
|
|
2
2
|
const ScreenRecorder = registerPlugin('ScreenRecorder', {
|
|
3
|
-
web: () => import('./web').then(m => new m.ScreenRecorderWeb()),
|
|
3
|
+
web: () => import('./web').then((m) => new m.ScreenRecorderWeb()),
|
|
4
4
|
});
|
|
5
5
|
export * from './definitions';
|
|
6
6
|
export { ScreenRecorder };
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,cAAc,GAAG,cAAc,CAAuB,gBAAgB,EAAE;IAC5E,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,cAAc,GAAG,cAAc,CAAuB,gBAAgB,EAAE;IAC5E,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;CAClE,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/esm/web.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
2
|
export class ScreenRecorderWeb extends WebPlugin {
|
|
3
3
|
async start() {
|
|
4
|
-
throw new Error(
|
|
4
|
+
throw new Error('Method not implemented.');
|
|
5
5
|
}
|
|
6
6
|
async stop() {
|
|
7
|
-
throw new Error(
|
|
7
|
+
throw new Error('Method not implemented.');
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=web.js.map
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IAC9C,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;CACF"}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var core = require('@capacitor/core');
|
|
6
4
|
|
|
7
5
|
const ScreenRecorder = core.registerPlugin('ScreenRecorder', {
|
|
8
|
-
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.ScreenRecorderWeb()),
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.ScreenRecorderWeb()),
|
|
9
7
|
});
|
|
10
8
|
|
|
11
9
|
class ScreenRecorderWeb extends core.WebPlugin {
|
|
12
10
|
async start() {
|
|
13
|
-
throw new Error(
|
|
11
|
+
throw new Error('Method not implemented.');
|
|
14
12
|
}
|
|
15
13
|
async stop() {
|
|
16
|
-
throw new Error(
|
|
14
|
+
throw new Error('Method not implemented.');
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
17
|
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst ScreenRecorder = registerPlugin('ScreenRecorder', {\n web: () => import('./web').then(m => new m.ScreenRecorderWeb()),\n});\nexport * from './definitions';\nexport { ScreenRecorder };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class ScreenRecorderWeb extends WebPlugin {\n async start() {\n throw new Error(
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst ScreenRecorder = registerPlugin('ScreenRecorder', {\n web: () => import('./web').then((m) => new m.ScreenRecorderWeb()),\n});\nexport * from './definitions';\nexport { ScreenRecorder };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class ScreenRecorderWeb extends WebPlugin {\n async start() {\n throw new Error('Method not implemented.');\n }\n async stop() {\n throw new Error('Method not implemented.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,cAAc,GAAGA,mBAAc,CAAC,gBAAgB,EAAE;AACxD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;AACrE,CAAC;;ACFM,MAAM,iBAAiB,SAASC,cAAS,CAAC;AACjD,IAAI,MAAM,KAAK,GAAG;AAClB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;AACnD,KAAK;AACL,IAAI,MAAM,IAAI,GAAG;AACjB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;AACnD,KAAK;AACL;;;;;;;;;"}
|
package/dist/plugin.js
CHANGED
|
@@ -2,15 +2,15 @@ var capacitorScreenRecorder = (function (exports, core) {
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const ScreenRecorder = core.registerPlugin('ScreenRecorder', {
|
|
5
|
-
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.ScreenRecorderWeb()),
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.ScreenRecorderWeb()),
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
class ScreenRecorderWeb extends core.WebPlugin {
|
|
9
9
|
async start() {
|
|
10
|
-
throw new Error(
|
|
10
|
+
throw new Error('Method not implemented.');
|
|
11
11
|
}
|
|
12
12
|
async stop() {
|
|
13
|
-
throw new Error(
|
|
13
|
+
throw new Error('Method not implemented.');
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -21,8 +21,6 @@ var capacitorScreenRecorder = (function (exports, core) {
|
|
|
21
21
|
|
|
22
22
|
exports.ScreenRecorder = ScreenRecorder;
|
|
23
23
|
|
|
24
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
25
|
-
|
|
26
24
|
return exports;
|
|
27
25
|
|
|
28
26
|
})({}, capacitorExports);
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst ScreenRecorder = registerPlugin('ScreenRecorder', {\n web: () => import('./web').then(m => new m.ScreenRecorderWeb()),\n});\nexport * from './definitions';\nexport { ScreenRecorder };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class ScreenRecorderWeb extends WebPlugin {\n async start() {\n throw new Error(
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst ScreenRecorder = registerPlugin('ScreenRecorder', {\n web: () => import('./web').then((m) => new m.ScreenRecorderWeb()),\n});\nexport * from './definitions';\nexport { ScreenRecorder };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class ScreenRecorderWeb extends WebPlugin {\n async start() {\n throw new Error('Method not implemented.');\n }\n async stop() {\n throw new Error('Method not implemented.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,cAAc,GAAGA,mBAAc,CAAC,gBAAgB,EAAE;IACxD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;IACrE,CAAC;;ICFM,MAAM,iBAAiB,SAASC,cAAS,CAAC;IACjD,IAAI,MAAM,KAAK,GAAG;IAClB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL,IAAI,MAAM,IAAI,GAAG;IACjB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,KAAK;IACL;;;;;;;;;;;;;;;"}
|
package/ios/Plugin/Wyler.swift
CHANGED
|
@@ -15,113 +15,113 @@ public enum ScreenRecorderError: Error {
|
|
|
15
15
|
case photoLibraryAccessNotGranted
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
final
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
18
|
+
public final class ScreenRecorder {
|
|
19
|
+
private var videoOutputURL: URL?
|
|
20
|
+
private var videoWriter: AVAssetWriter?
|
|
21
|
+
private var videoWriterInput: AVAssetWriterInput?
|
|
22
|
+
private var micAudioWriterInput: AVAssetWriterInput?
|
|
23
|
+
private var appAudioWriterInput: AVAssetWriterInput?
|
|
24
|
+
private var saveToCameraRoll = false
|
|
25
|
+
let recorder = RPScreenRecorder.shared()
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
Starts recording the content of the application screen. It works together with stopRecording
|
|
29
|
+
|
|
30
|
+
- Parameter outputURL: The output where the video will be saved. If nil, it saves it in the documents directory.
|
|
31
|
+
- Parameter size: The size of the video. If nil, it will use the app screen size.
|
|
32
|
+
- Parameter saveToCameraRoll: Whether to save it to camera roll. False by default.
|
|
33
|
+
- Parameter errorHandler: Called when an error is found
|
|
34
|
+
*/
|
|
35
|
+
public func startRecording(to outputURL: URL? = nil,
|
|
36
|
+
size: CGSize? = nil,
|
|
37
|
+
saveToCameraRoll: Bool = false,
|
|
38
|
+
handler: @escaping (Error?) -> Void) {
|
|
39
|
+
recorder.isMicrophoneEnabled = true
|
|
40
|
+
do {
|
|
41
|
+
try createVideoWriter(in: outputURL)
|
|
42
|
+
addVideoWriterInput(size: size)
|
|
43
|
+
self.micAudioWriterInput = createAndAddAudioInput()
|
|
44
|
+
self.appAudioWriterInput = createAndAddAudioInput()
|
|
45
|
+
startCapture(handler: handler)
|
|
46
|
+
} catch let err {
|
|
47
|
+
handler(err)
|
|
48
|
+
}
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
private func checkPhotoLibraryAuthorizationStatus() {
|
|
52
|
+
let status = PHPhotoLibrary.authorizationStatus()
|
|
53
|
+
if status == .notDetermined {
|
|
54
|
+
PHPhotoLibrary.requestAuthorization({ _ in })
|
|
55
|
+
}
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
|
|
58
|
+
private func createVideoWriter(in outputURL: URL? = nil) throws {
|
|
59
|
+
let newVideoOutputURL: URL
|
|
60
|
+
|
|
61
|
+
if let passedVideoOutput = outputURL {
|
|
62
|
+
self.videoOutputURL = passedVideoOutput
|
|
63
|
+
newVideoOutputURL = passedVideoOutput
|
|
64
|
+
} else {
|
|
65
|
+
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
|
|
66
|
+
newVideoOutputURL = URL(fileURLWithPath: documentsPath.appendingPathComponent("WylerNewVideo.mp4"))
|
|
67
|
+
self.videoOutputURL = newVideoOutputURL
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
do {
|
|
71
|
+
try FileManager.default.removeItem(at: newVideoOutputURL)
|
|
72
|
+
} catch {}
|
|
73
|
+
|
|
74
|
+
do {
|
|
75
|
+
try videoWriter = AVAssetWriter(outputURL: newVideoOutputURL, fileType: AVFileType.mp4)
|
|
76
|
+
} catch let writerError as NSError {
|
|
77
|
+
videoWriter = nil
|
|
78
|
+
throw writerError
|
|
79
|
+
}
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} catch {}
|
|
82
|
+
private func addVideoWriterInput(size: CGSize?) {
|
|
83
|
+
let passingSize: CGSize = size ?? UIScreen.main.bounds.size
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
let videoSettings: [String: Any] = [AVVideoCodecKey: AVVideoCodecType.h264,
|
|
86
|
+
AVVideoWidthKey: passingSize.width,
|
|
87
|
+
AVVideoHeightKey: passingSize.height]
|
|
88
|
+
|
|
89
|
+
let newVideoWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: videoSettings)
|
|
90
|
+
self.videoWriterInput = newVideoWriterInput
|
|
91
|
+
newVideoWriterInput.expectsMediaDataInRealTime = true
|
|
92
|
+
videoWriter?.add(newVideoWriterInput)
|
|
79
93
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
private func createAndAddAudioInput() -> AVAssetWriterInput {
|
|
96
|
-
let settings = [
|
|
97
|
-
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
|
|
98
|
-
AVSampleRateKey: 12000,
|
|
99
|
-
AVNumberOfChannelsKey: 1,
|
|
100
|
-
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
|
|
101
|
-
]
|
|
102
|
-
|
|
103
|
-
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: settings)
|
|
104
|
-
|
|
105
|
-
audioInput.expectsMediaDataInRealTime = true
|
|
106
|
-
videoWriter?.add(audioInput)
|
|
107
|
-
|
|
108
|
-
return audioInput
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private func startCapture(handler: @escaping (Error?) -> Void) {
|
|
112
|
-
guard recorder.isAvailable else {
|
|
113
|
-
return handler(ScreenRecorderError.notAvailable)
|
|
94
|
+
|
|
95
|
+
private func createAndAddAudioInput() -> AVAssetWriterInput {
|
|
96
|
+
let settings = [
|
|
97
|
+
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
|
|
98
|
+
AVSampleRateKey: 12000,
|
|
99
|
+
AVNumberOfChannelsKey: 1,
|
|
100
|
+
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: settings)
|
|
104
|
+
|
|
105
|
+
audioInput.expectsMediaDataInRealTime = true
|
|
106
|
+
videoWriter?.add(audioInput)
|
|
107
|
+
|
|
108
|
+
return audioInput
|
|
114
109
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
handler(passedError)
|
|
120
|
-
sent = true
|
|
121
|
-
}
|
|
110
|
+
|
|
111
|
+
private func startCapture(handler: @escaping (Error?) -> Void) {
|
|
112
|
+
guard recorder.isAvailable else {
|
|
113
|
+
return handler(ScreenRecorderError.notAvailable)
|
|
122
114
|
}
|
|
115
|
+
var sent = false
|
|
116
|
+
recorder.startCapture(handler: { (sampleBuffer, sampleType, passedError) in
|
|
117
|
+
if let passedError = passedError {
|
|
118
|
+
if !sent {
|
|
119
|
+
handler(passedError)
|
|
120
|
+
sent = true
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
switch sampleType {
|
|
125
125
|
case .video:
|
|
126
126
|
self.handleSampleBuffer(sampleBuffer: sampleBuffer)
|
|
127
127
|
case .audioApp:
|
|
@@ -130,77 +130,77 @@ final public class ScreenRecorder {
|
|
|
130
130
|
self.add(sample: sampleBuffer, to: self.micAudioWriterInput)
|
|
131
131
|
default:
|
|
132
132
|
break
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
private func handleSampleBuffer(sampleBuffer: CMSampleBuffer) {
|
|
142
|
-
if self.videoWriter?.status == AVAssetWriter.Status.unknown {
|
|
143
|
-
self.videoWriter?.startWriting()
|
|
144
|
-
self.videoWriter?.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sampleBuffer))
|
|
145
|
-
} else if self.videoWriter?.status == AVAssetWriter.Status.writing &&
|
|
146
|
-
self.videoWriterInput?.isReadyForMoreMediaData == true {
|
|
147
|
-
self.videoWriterInput?.append(sampleBuffer)
|
|
133
|
+
}
|
|
134
|
+
if !sent {
|
|
135
|
+
handler(nil)
|
|
136
|
+
sent = true
|
|
137
|
+
}
|
|
138
|
+
})
|
|
148
139
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
140
|
+
|
|
141
|
+
private func handleSampleBuffer(sampleBuffer: CMSampleBuffer) {
|
|
142
|
+
if self.videoWriter?.status == AVAssetWriter.Status.unknown {
|
|
143
|
+
self.videoWriter?.startWriting()
|
|
144
|
+
self.videoWriter?.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sampleBuffer))
|
|
145
|
+
} else if self.videoWriter?.status == AVAssetWriter.Status.writing &&
|
|
146
|
+
self.videoWriterInput?.isReadyForMoreMediaData == true {
|
|
147
|
+
self.videoWriterInput?.append(sampleBuffer)
|
|
148
|
+
}
|
|
154
149
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- Parameter errorHandler: Called when an error is found
|
|
161
|
-
*/
|
|
162
|
-
public func stoprecording(handler: @escaping (Error?) -> Void) {
|
|
163
|
-
recorder.stopCapture( handler: { error in
|
|
164
|
-
if let error = error {
|
|
165
|
-
handler(error)
|
|
166
|
-
} else {
|
|
167
|
-
self.videoWriterInput?.markAsFinished()
|
|
168
|
-
self.micAudioWriterInput?.markAsFinished()
|
|
169
|
-
self.appAudioWriterInput?.markAsFinished()
|
|
170
|
-
self.videoWriter?.finishWriting {
|
|
171
|
-
self.saveVideoToCameraRollAfterAuthorized(handler: handler)
|
|
150
|
+
|
|
151
|
+
private func add(sample: CMSampleBuffer, to writerInput: AVAssetWriterInput?) {
|
|
152
|
+
if writerInput?.isReadyForMoreMediaData ?? false {
|
|
153
|
+
writerInput?.append(sample)
|
|
172
154
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if
|
|
183
|
-
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
Stops recording the content of the application screen, after calling startRecording
|
|
159
|
+
|
|
160
|
+
- Parameter errorHandler: Called when an error is found
|
|
161
|
+
*/
|
|
162
|
+
public func stoprecording(handler: @escaping (Error?) -> Void) {
|
|
163
|
+
recorder.stopCapture( handler: { error in
|
|
164
|
+
if let error = error {
|
|
165
|
+
handler(error)
|
|
184
166
|
} else {
|
|
185
|
-
|
|
186
|
-
|
|
167
|
+
self.videoWriterInput?.markAsFinished()
|
|
168
|
+
self.micAudioWriterInput?.markAsFinished()
|
|
169
|
+
self.appAudioWriterInput?.markAsFinished()
|
|
170
|
+
self.videoWriter?.finishWriting {
|
|
171
|
+
self.saveVideoToCameraRollAfterAuthorized(handler: handler)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
187
174
|
})
|
|
188
175
|
}
|
|
189
|
-
}
|
|
190
176
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
177
|
+
private func saveVideoToCameraRollAfterAuthorized(handler: @escaping (Error?) -> Void) {
|
|
178
|
+
if PHPhotoLibrary.authorizationStatus() == .authorized {
|
|
179
|
+
self.saveVideoToCameraRoll(handler: handler)
|
|
180
|
+
} else {
|
|
181
|
+
PHPhotoLibrary.requestAuthorization({ (status) in
|
|
182
|
+
if status == .authorized {
|
|
183
|
+
self.saveVideoToCameraRoll(handler: handler)
|
|
184
|
+
} else {
|
|
185
|
+
handler(ScreenRecorderError.photoLibraryAccessNotGranted)
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
}
|
|
194
189
|
}
|
|
195
190
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
191
|
+
private func saveVideoToCameraRoll(handler: @escaping (Error?) -> Void) {
|
|
192
|
+
guard let videoOutputURL = self.videoOutputURL else {
|
|
193
|
+
return handler(nil)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
PHPhotoLibrary.shared().performChanges({
|
|
197
|
+
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoOutputURL)
|
|
198
|
+
}, completionHandler: { _, error in
|
|
199
|
+
if let error = error {
|
|
200
|
+
handler(error)
|
|
201
|
+
} else {
|
|
202
|
+
handler(nil)
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
206
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-screen-recorder",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"description": "Record device's screen",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -38,29 +38,34 @@
|
|
|
38
38
|
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
|
39
39
|
"swiftlint": "node-swiftlint",
|
|
40
40
|
"docgen": "docgen --api ScreenRecorderPlugin --output-readme README.md --output-json dist/docs.json",
|
|
41
|
-
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.
|
|
41
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
42
42
|
"clean": "rimraf ./dist",
|
|
43
43
|
"watch": "tsc --watch",
|
|
44
44
|
"prepublishOnly": "npm run build"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@capacitor/android": "^
|
|
48
|
-
"@capacitor/
|
|
49
|
-
"@capacitor/
|
|
50
|
-
"@capacitor/
|
|
47
|
+
"@capacitor/android": "^4.4.0",
|
|
48
|
+
"@capacitor/cli": "^4.4.0",
|
|
49
|
+
"@capacitor/core": "^4.4.0",
|
|
50
|
+
"@capacitor/docgen": "^0.2.0",
|
|
51
|
+
"@capacitor/ios": "^4.4.0",
|
|
51
52
|
"@ionic/eslint-config": "^0.3.0",
|
|
52
|
-
"@ionic/prettier-config": "^
|
|
53
|
+
"@ionic/prettier-config": "^2.0.0",
|
|
53
54
|
"@ionic/swiftlint-config": "^1.1.2",
|
|
54
|
-
"eslint": "^
|
|
55
|
-
"
|
|
56
|
-
"
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^5.42.1",
|
|
56
|
+
"@typescript-eslint/parser": "^5.42.1",
|
|
57
|
+
"eslint": "^8.27.0",
|
|
58
|
+
"eslint-plugin-import": "^2.26.0",
|
|
59
|
+
"husky": "^8.0.2",
|
|
60
|
+
"prettier": "^2.7.1",
|
|
61
|
+
"prettier-plugin-java": "^1.6.2",
|
|
57
62
|
"rimraf": "^3.0.2",
|
|
58
|
-
"rollup": "^2.
|
|
63
|
+
"rollup": "^3.2.5",
|
|
59
64
|
"swiftlint": "^1.0.1",
|
|
60
|
-
"typescript": "
|
|
65
|
+
"typescript": "^4.8.4"
|
|
61
66
|
},
|
|
62
67
|
"peerDependencies": {
|
|
63
|
-
"@capacitor/core": "^
|
|
68
|
+
"@capacitor/core": "^4.0.0"
|
|
64
69
|
},
|
|
65
70
|
"prettier": "@ionic/prettier-config",
|
|
66
71
|
"swiftlint": "@ionic/swiftlint-config",
|