react-native-webrtc-nitro 1.0.0 → 1.1.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.
@@ -85,7 +85,7 @@ void Muxer::tryWriteVideo ()
85
85
  {
86
86
  return;
87
87
  }
88
- std::vector<Packet> packets = audioEncoder.receive ();
88
+ std::vector<Packet> packets = videoEncoder.receive ();
89
89
  for (Packet &packet : packets)
90
90
  {
91
91
  packet->stream_index = videoStream->index;
@@ -0,0 +1,118 @@
1
+ #include "HybridMediaRecorder.hpp"
2
+ #include "FramePipe.hpp"
3
+ #include <filesystem>
4
+
5
+ using namespace margelo::nitro::webrtc;
6
+
7
+ auto HybridMediaRecorder::takePhoto (const std::string &file)
8
+ -> std::shared_ptr<Promise<void>>
9
+ {
10
+ if (mediaStream == nullptr)
11
+ {
12
+ throw std::runtime_error (
13
+ "MediaStream is not set for HybridMediaRecorder");
14
+ }
15
+
16
+ if (std::filesystem::path (file).extension () != ".png")
17
+ {
18
+ throw std::invalid_argument ("Only .png format is supported");
19
+ }
20
+
21
+ auto tracks = mediaStream->getVideoTracks ();
22
+ if (tracks.empty ())
23
+ {
24
+ throw std::runtime_error ("No video tracks available in MediaStream");
25
+ }
26
+ std::string srcPipeId = tracks[0]->get_srcPipeId ();
27
+ return Promise<void>::async (
28
+ [this, srcPipeId, file] () -> void
29
+ {
30
+ auto encoder = std::make_shared<FFmpeg::Encoder> (AV_CODEC_ID_PNG);
31
+ FrameCallback callback =
32
+ [this, encoder, file] (const std::string &, int subscriptionId,
33
+ const FFmpeg::Frame &frame)
34
+ {
35
+ FILE *f = fopen (file.c_str (), "wb");
36
+ if (!f)
37
+ {
38
+ throw std::invalid_argument ("Failed to open file " + file
39
+ + " for writing");
40
+ }
41
+ encoder->send (frame);
42
+ encoder->flush ();
43
+ for (const FFmpeg::Packet &packet : encoder->receive ())
44
+ {
45
+ fwrite (packet->data, 1, packet->size, f);
46
+ }
47
+ fclose (f);
48
+ ::unsubscribe (subscriptionId);
49
+ this->subscriptionId = -1;
50
+ };
51
+
52
+ this->subscriptionId
53
+ = subscribe ({ srcPipeId }, callback, nullptr);
54
+
55
+ // wait for the callback to be called
56
+ while (this->subscriptionId != -1)
57
+ {
58
+ std::this_thread::sleep_for (std::chrono::milliseconds (10));
59
+ }
60
+ });
61
+ }
62
+
63
+ void HybridMediaRecorder::startRecording (const std::string &file)
64
+ {
65
+ if (mediaStream == nullptr)
66
+ {
67
+ throw std::runtime_error (
68
+ "MediaStream is not set for HybridMediaRecorder");
69
+ }
70
+
71
+ if (std::filesystem::path (file).extension () != ".mp4")
72
+ {
73
+ throw std::invalid_argument ("Only .mp4 format is supported c++");
74
+ }
75
+ AVCodecID audioCodecId = AV_CODEC_ID_NONE;
76
+ AVCodecID videoCodecId = AV_CODEC_ID_NONE;
77
+ std::string audioPipeId = "";
78
+ std::string videoPipeId = "";
79
+ std::vector<std::string> pipeIds;
80
+ if (!mediaStream->getAudioTracks ().empty ())
81
+ {
82
+ audioPipeId = mediaStream->getAudioTracks ()[0]->get_srcPipeId ();
83
+ pipeIds.push_back (audioPipeId);
84
+ audioCodecId = AV_CODEC_ID_AAC;
85
+ }
86
+ if (!mediaStream->getVideoTracks ().empty ())
87
+ {
88
+ videoPipeId = mediaStream->getVideoTracks ()[0]->get_srcPipeId ();
89
+ pipeIds.push_back (videoPipeId);
90
+ videoCodecId = AV_CODEC_ID_H264;
91
+ }
92
+
93
+ auto muxer
94
+ = std::make_shared<FFmpeg::Muxer> (file, audioCodecId, videoCodecId);
95
+ FrameCallback callback
96
+ = [muxer, audioPipeId, videoPipeId] (const std::string &pipeId, int,
97
+ const FFmpeg::Frame &frame)
98
+ {
99
+ if (pipeId == audioPipeId)
100
+ {
101
+ muxer->writeAudio (frame);
102
+ }
103
+ if (pipeId == videoPipeId)
104
+ {
105
+ muxer->writeVideo (frame);
106
+ }
107
+ };
108
+
109
+ CleanupCallback cleanup = [muxer] (int) { muxer->stop (); };
110
+
111
+ subscriptionId = subscribe (pipeIds, callback, cleanup);
112
+ }
113
+
114
+ void HybridMediaRecorder::stopRecording ()
115
+ {
116
+ unsubscribe (subscriptionId);
117
+ subscriptionId = -1;
118
+ }
@@ -0,0 +1,36 @@
1
+ #pragma once
2
+ #include "HybridMediaRecorderSpec.hpp"
3
+ #include "HybridMediaStream.hpp"
4
+ #include <NitroModules/Promise.hpp>
5
+
6
+ namespace margelo::nitro::webrtc
7
+ {
8
+ class HybridMediaRecorder : public HybridMediaRecorderSpec
9
+ {
10
+ private:
11
+ std::shared_ptr<HybridMediaStream> mediaStream = nullptr;
12
+ int subscriptionId = -1;
13
+
14
+ public:
15
+ HybridMediaRecorder () : HybridObject (TAG), HybridMediaRecorderSpec ()
16
+ {
17
+ }
18
+
19
+ auto getStream () -> std::shared_ptr<HybridMediaStreamSpec> override
20
+ {
21
+ return mediaStream;
22
+ }
23
+
24
+ void setStream (
25
+ const std::shared_ptr<HybridMediaStreamSpec> &mediaStream) override
26
+ {
27
+ this->mediaStream
28
+ = std::dynamic_pointer_cast<HybridMediaStream> (mediaStream);
29
+ }
30
+
31
+ auto takePhoto (const std::string &file)
32
+ -> std::shared_ptr<Promise<void>> override;
33
+ void startRecording (const std::string &file) override;
34
+ void stopRecording () override;
35
+ };
36
+ } // namespace margelo::nitro::webrtc
@@ -11,13 +11,16 @@ constexpr int HEIGHT = 480;
11
11
 
12
12
  TEST (MuxerTest, testMuxerAAC)
13
13
  {
14
- std::string file = testing::TempDir () + "/test_file.mp4";
14
+ std::string file = "test_aac.mp4";
15
15
  Muxer muxer (file, AV_CODEC_ID_AAC, AV_CODEC_ID_NONE);
16
16
 
17
- Frame inputFrame (AV_SAMPLE_FMT_FLT, AUDIO_SAMPLE_RATE, 1,
18
- AUDIO_NB_SAMPLES);
19
- inputFrame.fillNoise ();
20
- muxer.writeAudio (inputFrame);
17
+ for (int i = 0; i < 1000; ++i)
18
+ {
19
+ Frame inputFrame (AV_SAMPLE_FMT_FLT, AUDIO_SAMPLE_RATE, 1,
20
+ AUDIO_NB_SAMPLES, i * AUDIO_NB_SAMPLES);
21
+ inputFrame.fillNoise ();
22
+ muxer.writeAudio (inputFrame);
23
+ }
21
24
  muxer.stop ();
22
25
 
23
26
  EXPECT_TRUE (std::filesystem::exists (file));
@@ -25,46 +28,29 @@ TEST (MuxerTest, testMuxerAAC)
25
28
 
26
29
  TEST (MuxerTest, testMuxerH264)
27
30
  {
28
- std::string file = testing::TempDir () + "/test_file.mp4";
29
-
31
+ std::string file = "test_h264.mp4";
30
32
  Muxer muxer (file, AV_CODEC_ID_NONE, AV_CODEC_ID_H264);
31
- Frame inputFrame (AV_PIX_FMT_NV12, WIDTH, HEIGHT);
32
- inputFrame.fillNoise ();
33
- muxer.writeVideo (inputFrame);
34
- muxer.stop ();
35
-
36
- EXPECT_TRUE (std::filesystem::exists (file));
37
- }
38
-
39
- TEST (MuxerTest, testMuxerVideo)
40
- {
41
- std::string file = testing::TempDir () + "/test_file.mp4";
42
- Muxer muxer (file, AV_CODEC_ID_AAC, AV_CODEC_ID_H264);
43
-
44
- Frame audioFrame (AV_SAMPLE_FMT_FLT, AUDIO_SAMPLE_RATE, 1,
45
- AUDIO_NB_SAMPLES);
46
- Frame videoFrame (AV_PIX_FMT_NV12, WIDTH, HEIGHT);
47
- audioFrame.fillNoise ();
48
- videoFrame.fillNoise ();
49
- muxer.writeAudio (audioFrame);
50
- muxer.writeVideo (videoFrame);
51
33
 
34
+ for (int i = 0; i < 1000; ++i)
35
+ {
36
+ Frame inputFrame (AV_PIX_FMT_NV12, WIDTH, HEIGHT, i * 3000);
37
+ inputFrame.fillNoise ();
38
+ muxer.writeVideo (inputFrame);
39
+ }
52
40
  muxer.stop ();
53
41
  EXPECT_TRUE (std::filesystem::exists (file));
54
42
  }
55
43
 
56
- TEST (MuxerTest, testSaveMp4)
44
+ TEST (MuxerTest, testMuxerVideo)
57
45
  {
58
46
  std::string file = "output.mp4";
59
47
  Muxer muxer (file, AV_CODEC_ID_AAC, AV_CODEC_ID_H264);
60
- constexpr int LOOPS = 1000;
61
- constexpr int VIDEO_SAMPLES = 3000;
62
48
 
63
- for (int i = 0; i < LOOPS; ++i)
49
+ for (int i = 0; i < 1000; ++i)
64
50
  {
65
51
  Frame audioFrame (AV_SAMPLE_FMT_FLT, AUDIO_SAMPLE_RATE, 1,
66
52
  AUDIO_NB_SAMPLES, i * AUDIO_NB_SAMPLES);
67
- Frame videoFrame (AV_PIX_FMT_NV12, WIDTH, HEIGHT, i * VIDEO_SAMPLES);
53
+ Frame videoFrame (AV_PIX_FMT_NV12, WIDTH, HEIGHT, i * 3000);
68
54
  audioFrame.fillNoise ();
69
55
  videoFrame.fillNoise ();
70
56
  muxer.writeAudio (audioFrame);
@@ -91,4 +91,15 @@ Object.keys(_RTCRtpTransceiver).forEach(function (key) {
91
91
  }
92
92
  });
93
93
  });
94
+ var _MediaRecorder = require("./specs/MediaRecorder.nitro");
95
+ Object.keys(_MediaRecorder).forEach(function (key) {
96
+ if (key === "default" || key === "__esModule") return;
97
+ if (key in exports && exports[key] === _MediaRecorder[key]) return;
98
+ Object.defineProperty(exports, key, {
99
+ enumerable: true,
100
+ get: function () {
101
+ return _MediaRecorder[key];
102
+ }
103
+ });
104
+ });
94
105
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_WebrtcView","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_MediaDevices","_MediaStream","_MediaStreamTrack","_RTCPeerConnection","_RTCRtpSender","_RTCRtpReceiver","_RTCRtpTransceiver"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_WebrtcView","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_MediaDevices","_MediaStream","_MediaStreamTrack","_RTCPeerConnection","_RTCRtpSender","_RTCRtpReceiver","_RTCRtpTransceiver","_MediaRecorder"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MediaRecorder = void 0;
7
+ var _reactNativeNitroModules = require("react-native-nitro-modules");
8
+ const MediaRecorderConstructor = (0, _reactNativeNitroModules.getHybridObjectConstructor)('MediaRecorder');
9
+ const MediaRecorderExport = exports.MediaRecorder = new Proxy(MediaRecorderConstructor, {
10
+ construct(target, args) {
11
+ const instance = new target();
12
+ instance.stream = args[0];
13
+ return instance;
14
+ }
15
+ });
16
+ //# sourceMappingURL=MediaRecorder.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNativeNitroModules","require","MediaRecorderConstructor","getHybridObjectConstructor","MediaRecorderExport","exports","MediaRecorder","Proxy","construct","target","args","instance","stream"],"sourceRoot":"../../../src","sources":["specs/MediaRecorder.nitro.ts"],"mappings":";;;;;;AACA,IAAAA,wBAAA,GAAAC,OAAA;AAUA,MAAMC,wBAAwB,GAC5B,IAAAC,mDAA0B,EAAgB,eAAe,CAAC;AAE5D,MAAMC,mBAAmB,GAAAC,OAAA,CAAAC,aAAA,GAAG,IAAIC,KAAK,CAACL,wBAAwB,EAAE;EAC9DM,SAASA,CAACC,MAAM,EAAEC,IAAI,EAAE;IACtB,MAAMC,QAAQ,GAAG,IAAIF,MAAM,CAAC,CAAC;IAC7BE,QAAQ,CAACC,MAAM,GAAGF,IAAI,CAAC,CAAC,CAAgB;IACxC,OAAOC,QAAQ;EACjB;AACF,CAAC,CAAiD","ignoreList":[]}
@@ -8,4 +8,5 @@ export * from './specs/RTCPeerConnection.nitro';
8
8
  export * from './specs/RTCRtpSender.nitro';
9
9
  export * from './specs/RTCRtpReceiver.nitro';
10
10
  export * from './specs/RTCRtpTransceiver.nitro';
11
+ export * from './specs/MediaRecorder.nitro';
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,cAAc,oBAAoB;AAClC,cAAc,4BAA4B;AAC1C,cAAc,2BAA2B;AACzC,cAAc,gCAAgC;AAC9C,cAAc,iCAAiC;AAC/C,cAAc,4BAA4B;AAC1C,cAAc,8BAA8B;AAC5C,cAAc,iCAAiC","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,cAAc,oBAAoB;AAClC,cAAc,4BAA4B;AAC1C,cAAc,2BAA2B;AACzC,cAAc,gCAAgC;AAC9C,cAAc,iCAAiC;AAC/C,cAAc,4BAA4B;AAC1C,cAAc,8BAA8B;AAC5C,cAAc,iCAAiC;AAC/C,cAAc,6BAA6B","ignoreList":[]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ import { getHybridObjectConstructor } from 'react-native-nitro-modules';
4
+ const MediaRecorderConstructor = getHybridObjectConstructor('MediaRecorder');
5
+ const MediaRecorderExport = new Proxy(MediaRecorderConstructor, {
6
+ construct(target, args) {
7
+ const instance = new target();
8
+ instance.stream = args[0];
9
+ return instance;
10
+ }
11
+ });
12
+ export { MediaRecorderExport as MediaRecorder };
13
+ //# sourceMappingURL=MediaRecorder.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getHybridObjectConstructor","MediaRecorderConstructor","MediaRecorderExport","Proxy","construct","target","args","instance","stream","MediaRecorder"],"sourceRoot":"../../../src","sources":["specs/MediaRecorder.nitro.ts"],"mappings":";;AACA,SAASA,0BAA0B,QAAQ,4BAA4B;AAUvE,MAAMC,wBAAwB,GAC5BD,0BAA0B,CAAgB,eAAe,CAAC;AAE5D,MAAME,mBAAmB,GAAG,IAAIC,KAAK,CAACF,wBAAwB,EAAE;EAC9DG,SAASA,CAACC,MAAM,EAAEC,IAAI,EAAE;IACtB,MAAMC,QAAQ,GAAG,IAAIF,MAAM,CAAC,CAAC;IAC7BE,QAAQ,CAACC,MAAM,GAAGF,IAAI,CAAC,CAAC,CAAgB;IACxC,OAAOC,QAAQ;EACjB;AACF,CAAC,CAAiD;AAGlD,SAASL,mBAAmB,IAAIO,aAAa","ignoreList":[]}
@@ -6,4 +6,5 @@ export * from './specs/RTCPeerConnection.nitro';
6
6
  export * from './specs/RTCRtpSender.nitro';
7
7
  export * from './specs/RTCRtpReceiver.nitro';
8
8
  export * from './specs/RTCRtpTransceiver.nitro';
9
+ export * from './specs/MediaRecorder.nitro';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { type HybridObject } from 'react-native-nitro-modules';
2
+ import { MediaStream } from './MediaStream.nitro';
3
+ interface MediaRecorder extends HybridObject<{
4
+ ios: 'c++';
5
+ android: 'c++';
6
+ }> {
7
+ stream: MediaStream;
8
+ takePhoto(file: string): Promise<void>;
9
+ startRecording(file: string): void;
10
+ stopRecording(): void;
11
+ }
12
+ declare const MediaRecorderExport: {
13
+ new (stream: MediaStream): MediaRecorder;
14
+ };
15
+ type MediaRecorderExport = MediaRecorder;
16
+ export { MediaRecorderExport as MediaRecorder };
17
+ //# sourceMappingURL=MediaRecorder.nitro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MediaRecorder.nitro.d.ts","sourceRoot":"","sources":["../../../../src/specs/MediaRecorder.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEjD,UAAU,aAAc,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC;IAC1E,MAAM,EAAE,WAAW,CAAA;IACnB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,IAAI,IAAI,CAAA;CACtB;AAKD,QAAA,MAAM,mBAAmB,EAMnB;IAAE,KAAK,MAAM,EAAE,WAAW,GAAG,aAAa,CAAA;CAAE,CAAA;AAElD,KAAK,mBAAmB,GAAG,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,IAAI,aAAa,EAAE,CAAA"}
package/nitro.json CHANGED
@@ -34,6 +34,9 @@
34
34
  "MediaDevices": {
35
35
  "cpp": "HybridMediaDevices"
36
36
  },
37
+ "MediaRecorder": {
38
+ "cpp": "HybridMediaRecorder"
39
+ },
37
40
  "RTCRtpSender": {
38
41
  "cpp": "HybridRTCRtpSender"
39
42
  },
@@ -35,6 +35,7 @@ target_sources(
35
35
  # Shared Nitrogen C++ sources
36
36
  ../nitrogen/generated/shared/c++/HybridCameraSpec.cpp
37
37
  ../nitrogen/generated/shared/c++/HybridMediaDevicesSpec.cpp
38
+ ../nitrogen/generated/shared/c++/HybridMediaRecorderSpec.cpp
38
39
  ../nitrogen/generated/shared/c++/HybridMediaStreamSpec.cpp
39
40
  ../nitrogen/generated/shared/c++/HybridMediaStreamTrackSpec.cpp
40
41
  ../nitrogen/generated/shared/c++/HybridMicrophoneSpec.cpp
@@ -23,6 +23,7 @@
23
23
  #include "HybridMediaStreamTrack.hpp"
24
24
  #include "HybridMediaStream.hpp"
25
25
  #include "HybridMediaDevices.hpp"
26
+ #include "HybridMediaRecorder.hpp"
26
27
  #include "HybridRTCRtpSender.hpp"
27
28
  #include "HybridRTCRtpReceiver.hpp"
28
29
  #include "HybridRTCRtpTransceiver.hpp"
@@ -94,6 +95,15 @@ int initialize(JavaVM* vm) {
94
95
  return std::make_shared<HybridMediaDevices>();
95
96
  }
96
97
  );
98
+ HybridObjectRegistry::registerHybridObjectConstructor(
99
+ "MediaRecorder",
100
+ []() -> std::shared_ptr<HybridObject> {
101
+ static_assert(std::is_default_constructible_v<HybridMediaRecorder>,
102
+ "The HybridObject \"HybridMediaRecorder\" is not default-constructible! "
103
+ "Create a public constructor that takes zero arguments to be able to autolink this HybridObject.");
104
+ return std::make_shared<HybridMediaRecorder>();
105
+ }
106
+ );
97
107
  HybridObjectRegistry::registerHybridObjectConstructor(
98
108
  "RTCRtpSender",
99
109
  []() -> std::shared_ptr<HybridObject> {
@@ -16,6 +16,7 @@
16
16
  #include "HybridMediaStream.hpp"
17
17
  #include "HybridWebrtcViewSpecSwift.hpp"
18
18
  #include "HybridMediaDevices.hpp"
19
+ #include "HybridMediaRecorder.hpp"
19
20
  #include "HybridRTCRtpSender.hpp"
20
21
  #include "HybridRTCRtpReceiver.hpp"
21
22
  #include "HybridRTCRtpTransceiver.hpp"
@@ -78,6 +79,15 @@
78
79
  return std::make_shared<HybridMediaDevices>();
79
80
  }
80
81
  );
82
+ HybridObjectRegistry::registerHybridObjectConstructor(
83
+ "MediaRecorder",
84
+ []() -> std::shared_ptr<HybridObject> {
85
+ static_assert(std::is_default_constructible_v<HybridMediaRecorder>,
86
+ "The HybridObject \"HybridMediaRecorder\" is not default-constructible! "
87
+ "Create a public constructor that takes zero arguments to be able to autolink this HybridObject.");
88
+ return std::make_shared<HybridMediaRecorder>();
89
+ }
90
+ );
81
91
  HybridObjectRegistry::registerHybridObjectConstructor(
82
92
  "RTCRtpSender",
83
93
  []() -> std::shared_ptr<HybridObject> {
@@ -0,0 +1,25 @@
1
+ ///
2
+ /// HybridMediaRecorderSpec.cpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2025 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #include "HybridMediaRecorderSpec.hpp"
9
+
10
+ namespace margelo::nitro::webrtc {
11
+
12
+ void HybridMediaRecorderSpec::loadHybridMethods() {
13
+ // load base methods/properties
14
+ HybridObject::loadHybridMethods();
15
+ // load custom methods/properties
16
+ registerHybrids(this, [](Prototype& prototype) {
17
+ prototype.registerHybridGetter("stream", &HybridMediaRecorderSpec::getStream);
18
+ prototype.registerHybridSetter("stream", &HybridMediaRecorderSpec::setStream);
19
+ prototype.registerHybridMethod("takePhoto", &HybridMediaRecorderSpec::takePhoto);
20
+ prototype.registerHybridMethod("startRecording", &HybridMediaRecorderSpec::startRecording);
21
+ prototype.registerHybridMethod("stopRecording", &HybridMediaRecorderSpec::stopRecording);
22
+ });
23
+ }
24
+
25
+ } // namespace margelo::nitro::webrtc
@@ -0,0 +1,69 @@
1
+ ///
2
+ /// HybridMediaRecorderSpec.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2025 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/HybridObject.hpp>)
11
+ #include <NitroModules/HybridObject.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+
16
+ // Forward declaration of `HybridMediaStreamSpec` to properly resolve imports.
17
+ namespace margelo::nitro::webrtc { class HybridMediaStreamSpec; }
18
+
19
+ #include <memory>
20
+ #include "HybridMediaStreamSpec.hpp"
21
+ #include <NitroModules/Promise.hpp>
22
+ #include <string>
23
+
24
+ namespace margelo::nitro::webrtc {
25
+
26
+ using namespace margelo::nitro;
27
+
28
+ /**
29
+ * An abstract base class for `MediaRecorder`
30
+ * Inherit this class to create instances of `HybridMediaRecorderSpec` in C++.
31
+ * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.
32
+ * @example
33
+ * ```cpp
34
+ * class HybridMediaRecorder: public HybridMediaRecorderSpec {
35
+ * public:
36
+ * HybridMediaRecorder(...): HybridObject(TAG) { ... }
37
+ * // ...
38
+ * };
39
+ * ```
40
+ */
41
+ class HybridMediaRecorderSpec: public virtual HybridObject {
42
+ public:
43
+ // Constructor
44
+ explicit HybridMediaRecorderSpec(): HybridObject(TAG) { }
45
+
46
+ // Destructor
47
+ ~HybridMediaRecorderSpec() override = default;
48
+
49
+ public:
50
+ // Properties
51
+ virtual std::shared_ptr<HybridMediaStreamSpec> getStream() = 0;
52
+ virtual void setStream(const std::shared_ptr<HybridMediaStreamSpec>& stream) = 0;
53
+
54
+ public:
55
+ // Methods
56
+ virtual std::shared_ptr<Promise<void>> takePhoto(const std::string& file) = 0;
57
+ virtual void startRecording(const std::string& file) = 0;
58
+ virtual void stopRecording() = 0;
59
+
60
+ protected:
61
+ // Hybrid Setup
62
+ void loadHybridMethods() override;
63
+
64
+ protected:
65
+ // Tag for logging
66
+ static constexpr auto TAG = "MediaRecorder";
67
+ };
68
+
69
+ } // namespace margelo::nitro::webrtc
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-webrtc-nitro",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Nitro WebRTC module for React Native",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",
package/src/index.ts CHANGED
@@ -6,3 +6,4 @@ export * from './specs/RTCPeerConnection.nitro'
6
6
  export * from './specs/RTCRtpSender.nitro'
7
7
  export * from './specs/RTCRtpReceiver.nitro'
8
8
  export * from './specs/RTCRtpTransceiver.nitro'
9
+ export * from './specs/MediaRecorder.nitro'
@@ -0,0 +1,24 @@
1
+ import { type HybridObject } from 'react-native-nitro-modules'
2
+ import { getHybridObjectConstructor } from 'react-native-nitro-modules'
3
+ import { MediaStream } from './MediaStream.nitro'
4
+
5
+ interface MediaRecorder extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
6
+ stream: MediaStream
7
+ takePhoto(file: string): Promise<void>
8
+ startRecording(file: string): void
9
+ stopRecording(): void
10
+ }
11
+
12
+ const MediaRecorderConstructor =
13
+ getHybridObjectConstructor<MediaRecorder>('MediaRecorder')
14
+
15
+ const MediaRecorderExport = new Proxy(MediaRecorderConstructor, {
16
+ construct(target, args) {
17
+ const instance = new target()
18
+ instance.stream = args[0] as MediaStream
19
+ return instance
20
+ },
21
+ }) as { new (stream: MediaStream): MediaRecorder }
22
+
23
+ type MediaRecorderExport = MediaRecorder
24
+ export { MediaRecorderExport as MediaRecorder }