noobs 0.0.115 → 0.0.130
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/dist/data/obs-plugins/obs-filters/LUTs/black_and_white.png +0 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/grayscale.cube +32769 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/grayscale.png +0 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/invert.png +0 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/original.cube +33 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/original.png +0 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/posterize.png +0 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/red_isolated.png +0 -0
- package/dist/data/obs-plugins/obs-filters/LUTs/teal_lows_orange_highs.png +0 -0
- package/dist/data/obs-plugins/obs-filters/blend_add_filter.effect +54 -0
- package/dist/data/obs-plugins/obs-filters/blend_mul_filter.effect +54 -0
- package/dist/data/obs-plugins/obs-filters/blend_sub_filter.effect +54 -0
- package/dist/data/obs-plugins/obs-filters/chroma_key_filter.effect +99 -0
- package/dist/data/obs-plugins/obs-filters/chroma_key_filter_v2.effect +111 -0
- package/dist/data/obs-plugins/obs-filters/color.effect +95 -0
- package/dist/data/obs-plugins/obs-filters/color_correction_filter.effect +74 -0
- package/dist/data/obs-plugins/obs-filters/color_grade_filter.effect +177 -0
- package/dist/data/obs-plugins/obs-filters/color_key_filter.effect +65 -0
- package/dist/data/obs-plugins/obs-filters/color_key_filter_v2.effect +77 -0
- package/dist/data/obs-plugins/obs-filters/crop_filter.effect +95 -0
- package/dist/data/obs-plugins/obs-filters/hdr_tonemap_filter.effect +97 -0
- package/dist/data/obs-plugins/obs-filters/locale/af-ZA.ini +89 -0
- package/dist/data/obs-plugins/obs-filters/locale/ar-SA.ini +133 -0
- package/dist/data/obs-plugins/obs-filters/locale/az-AZ.ini +1 -0
- package/dist/data/obs-plugins/obs-filters/locale/ba-RU.ini +19 -0
- package/dist/data/obs-plugins/obs-filters/locale/be-BY.ini +134 -0
- package/dist/data/obs-plugins/obs-filters/locale/bg-BG.ini +71 -0
- package/dist/data/obs-plugins/obs-filters/locale/bn-BD.ini +106 -0
- package/dist/data/obs-plugins/obs-filters/locale/ca-ES.ini +128 -0
- package/dist/data/obs-plugins/obs-filters/locale/cs-CZ.ini +130 -0
- package/dist/data/obs-plugins/obs-filters/locale/da-DK.ini +119 -0
- package/dist/data/obs-plugins/obs-filters/locale/de-DE.ini +113 -0
- package/dist/data/obs-plugins/obs-filters/locale/el-GR.ini +128 -0
- package/dist/data/obs-plugins/obs-filters/locale/en-GB.ini +12 -0
- package/dist/data/obs-plugins/obs-filters/locale/en-US.ini +138 -0
- package/dist/data/obs-plugins/obs-filters/locale/eo-UY.ini +1 -0
- package/dist/data/obs-plugins/obs-filters/locale/es-ES.ini +129 -0
- package/dist/data/obs-plugins/obs-filters/locale/et-EE.ini +132 -0
- package/dist/data/obs-plugins/obs-filters/locale/eu-ES.ini +127 -0
- package/dist/data/obs-plugins/obs-filters/locale/fa-IR.ini +137 -0
- package/dist/data/obs-plugins/obs-filters/locale/fi-FI.ini +127 -0
- package/dist/data/obs-plugins/obs-filters/locale/fil-PH.ini +111 -0
- package/dist/data/obs-plugins/obs-filters/locale/fr-FR.ini +124 -0
- package/dist/data/obs-plugins/obs-filters/locale/gd-GB.ini +94 -0
- package/dist/data/obs-plugins/obs-filters/locale/gl-ES.ini +132 -0
- package/dist/data/obs-plugins/obs-filters/locale/he-IL.ini +135 -0
- package/dist/data/obs-plugins/obs-filters/locale/hi-IN.ini +134 -0
- package/dist/data/obs-plugins/obs-filters/locale/hr-HR.ini +80 -0
- package/dist/data/obs-plugins/obs-filters/locale/hu-HU.ini +131 -0
- package/dist/data/obs-plugins/obs-filters/locale/hy-AM.ini +130 -0
- package/dist/data/obs-plugins/obs-filters/locale/id-ID.ini +112 -0
- package/dist/data/obs-plugins/obs-filters/locale/it-IT.ini +130 -0
- package/dist/data/obs-plugins/obs-filters/locale/ja-JP.ini +134 -0
- package/dist/data/obs-plugins/obs-filters/locale/ka-GE.ini +133 -0
- package/dist/data/obs-plugins/obs-filters/locale/kaa.ini +41 -0
- package/dist/data/obs-plugins/obs-filters/locale/kab-KAB.ini +56 -0
- package/dist/data/obs-plugins/obs-filters/locale/kmr-TR.ini +126 -0
- package/dist/data/obs-plugins/obs-filters/locale/ko-KR.ini +134 -0
- package/dist/data/obs-plugins/obs-filters/locale/ms-MY.ini +131 -0
- package/dist/data/obs-plugins/obs-filters/locale/nb-NO.ini +115 -0
- package/dist/data/obs-plugins/obs-filters/locale/nl-NL.ini +111 -0
- package/dist/data/obs-plugins/obs-filters/locale/nn-NO.ini +19 -0
- package/dist/data/obs-plugins/obs-filters/locale/pl-PL.ini +127 -0
- package/dist/data/obs-plugins/obs-filters/locale/pt-BR.ini +128 -0
- package/dist/data/obs-plugins/obs-filters/locale/pt-PT.ini +130 -0
- package/dist/data/obs-plugins/obs-filters/locale/ro-RO.ini +125 -0
- package/dist/data/obs-plugins/obs-filters/locale/ru-RU.ini +135 -0
- package/dist/data/obs-plugins/obs-filters/locale/si-LK.ini +44 -0
- package/dist/data/obs-plugins/obs-filters/locale/sk-SK.ini +131 -0
- package/dist/data/obs-plugins/obs-filters/locale/sl-SI.ini +133 -0
- package/dist/data/obs-plugins/obs-filters/locale/sr-CS.ini +90 -0
- package/dist/data/obs-plugins/obs-filters/locale/sr-SP.ini +97 -0
- package/dist/data/obs-plugins/obs-filters/locale/sv-SE.ini +129 -0
- package/dist/data/obs-plugins/obs-filters/locale/szl-PL.ini +94 -0
- package/dist/data/obs-plugins/obs-filters/locale/ta-IN.ini +28 -0
- package/dist/data/obs-plugins/obs-filters/locale/th-TH.ini +132 -0
- package/dist/data/obs-plugins/obs-filters/locale/tl-PH.ini +64 -0
- package/dist/data/obs-plugins/obs-filters/locale/tr-TR.ini +129 -0
- package/dist/data/obs-plugins/obs-filters/locale/tt-RU.ini +27 -0
- package/dist/data/obs-plugins/obs-filters/locale/ug-CN.ini +133 -0
- package/dist/data/obs-plugins/obs-filters/locale/uk-UA.ini +135 -0
- package/dist/data/obs-plugins/obs-filters/locale/vi-VN.ini +131 -0
- package/dist/data/obs-plugins/obs-filters/locale/zh-CN.ini +138 -0
- package/dist/data/obs-plugins/obs-filters/locale/zh-TW.ini +136 -0
- package/dist/data/obs-plugins/obs-filters/luma_key_filter.effect +52 -0
- package/dist/data/obs-plugins/obs-filters/luma_key_filter_v2.effect +54 -0
- package/dist/data/obs-plugins/obs-filters/mask_alpha_filter.effect +54 -0
- package/dist/data/obs-plugins/obs-filters/mask_color_filter.effect +55 -0
- package/dist/data/obs-plugins/obs-filters/rtx_greenscreen.effect +183 -0
- package/dist/data/obs-plugins/obs-filters/sharpness.effect +76 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ar-SA.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/be-BY.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/bg-BG.ini +2 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ca-ES.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/cs-CZ.ini +55 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/da-DK.ini +54 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/de-DE.ini +55 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/en-GB.ini +9 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/en-US.ini +75 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/es-ES.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/et-EE.ini +36 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/fa-IR.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/fi-FI.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/fr-FR.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/gl-ES.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/he-IL.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/hi-IN.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/hu-HU.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/id-ID.ini +55 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/is-IS.ini +2 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/it-IT.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ja-JP.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ka-GE.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/kaa.ini +13 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/kmr-TR.ini +20 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ko-KR.ini +58 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ms-MY.ini +58 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/nb-NO.ini +24 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/nl-NL.ini +54 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/nn-NO.ini +1 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/pl-PL.ini +55 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/pt-BR.ini +58 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/pt-PT.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ru-RU.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/sk-SK.ini +56 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/sv-SE.ini +58 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/th-TH.ini +59 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/tr-TR.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/tt-RU.ini +2 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/ug-CN.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/uk-UA.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/vi-VN.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/zh-CN.ini +60 -0
- package/dist/data/obs-plugins/obs-nvenc/locale/zh-TW.ini +60 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/af-ZA.ini +19 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ar-SA.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ba-RU.ini +2 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/be-BY.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/bg-BG.ini +7 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/bn-BD.ini +8 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ca-ES.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/cs-CZ.ini +19 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/da-DK.ini +19 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/de-DE.ini +19 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/el-GR.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/en-GB.ini +1 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/en-US.ini +21 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/es-ES.ini +19 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/et-EE.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/eu-ES.ini +11 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/fa-IR.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/fi-FI.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/fil-PH.ini +11 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/fr-FR.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/gd-GB.ini +8 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/gl-ES.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/he-IL.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/hi-IN.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/hr-HR.ini +14 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/hu-HU.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/hy-AM.ini +13 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/id-ID.ini +18 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/is-IS.ini +1 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/it-IT.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ja-JP.ini +16 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ka-GE.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/kaa.ini +10 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/kab-KAB.ini +5 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/kmr-TR.ini +12 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ko-KR.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ms-MY.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/nb-NO.ini +16 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/nl-NL.ini +18 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/nn-NO.ini +2 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/oc-FR.ini +1 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/pl-PL.ini +16 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/pt-BR.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/pt-PT.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ro-RO.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ru-RU.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/si-LK.ini +8 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/sk-SK.ini +19 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/sl-SI.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/sr-CS.ini +6 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/sr-SP.ini +10 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/sv-SE.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ta-IN.ini +2 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/th-TH.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/tl-PH.ini +5 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/tr-TR.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/tt-RU.ini +3 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/ug-CN.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/uk-UA.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/vi-VN.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/zh-CN.ini +20 -0
- package/dist/data/obs-plugins/obs-qsv11/locale/zh-TW.ini +20 -0
- package/dist/noobs.node +0 -0
- package/dist/obs-plugins/image-source.dll +0 -0
- package/dist/obs-plugins/obs-filters.dll +0 -0
- package/dist/obs-plugins/obs-nvenc.dll +0 -0
- package/dist/obs-plugins/obs-qsv11.dll +0 -0
- package/dist/obs-plugins/obs-x264.dll +0 -0
- package/dist/obs-plugins/win-capture.dll +0 -0
- package/dist/obs-plugins/win-wasapi.dll +0 -0
- package/index.d.ts +5 -8
- package/package.json +1 -1
- package/src/main.cpp +34 -65
- package/src/obs_interface.cpp +295 -203
- package/src/obs_interface.h +28 -27
package/src/obs_interface.cpp
CHANGED
|
@@ -55,9 +55,10 @@ void ObsInterface::list_output_types()
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
void ObsInterface::load_module(const char* module, const char* data) {
|
|
58
|
+
void ObsInterface::load_module(const char* module, const char* data, bool allowFail) {
|
|
59
59
|
blog(LOG_INFO, "Loading module: %s", module);
|
|
60
60
|
blog(LOG_INFO, "Data path: %s", data);
|
|
61
|
+
blog(LOG_INFO, "Allow fail: %d", allowFail);
|
|
61
62
|
|
|
62
63
|
obs_module_t *ptr = NULL;
|
|
63
64
|
int success = obs_open_module(&ptr, module, data);
|
|
@@ -69,8 +70,12 @@ void ObsInterface::load_module(const char* module, const char* data) {
|
|
|
69
70
|
|
|
70
71
|
bool initmod = obs_init_module(ptr);
|
|
71
72
|
|
|
72
|
-
if (
|
|
73
|
-
blog(
|
|
73
|
+
if (initmod) {
|
|
74
|
+
blog(LOG_INFO, "Module initialized successfully!");
|
|
75
|
+
} else if (allowFail) {
|
|
76
|
+
blog(LOG_INFO, "Module initialization failed, but allowed to fail: %s", module);
|
|
77
|
+
} else {
|
|
78
|
+
blog(LOG_ERROR, "Failed to initialize module: %s", module);
|
|
74
79
|
throw std::runtime_error("Module initialization failed!");
|
|
75
80
|
}
|
|
76
81
|
}
|
|
@@ -189,17 +194,23 @@ void ObsInterface::init_obs(const std::string& distPath) {
|
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
std::vector<std::string> modules = {
|
|
192
|
-
"obs-x264",
|
|
193
|
-
"obs-ffmpeg",
|
|
197
|
+
"obs-x264", // Software encoder.
|
|
198
|
+
"obs-ffmpeg", // Contains AMF (AMD) encoder support.
|
|
194
199
|
"win-capture", // Required for basically all forms of capture on Windows.
|
|
195
200
|
"image-source", // Required for image sources.
|
|
196
|
-
"win-wasapi"
|
|
201
|
+
"win-wasapi", // Required for WASAPI audio input.
|
|
202
|
+
"obs-nvenc", // Required for NVENC video encoding.
|
|
203
|
+
"obs-qsv11", // Required for QSV video encoding.
|
|
204
|
+
"obs-filters" // Required for audio filters.
|
|
197
205
|
};
|
|
198
206
|
|
|
199
207
|
for (const auto& module : modules) {
|
|
200
208
|
std::string modulePath = pluginPath + module + ".dll";
|
|
201
209
|
std::string moduleDataPath = pluginDataPath + module;
|
|
202
|
-
|
|
210
|
+
|
|
211
|
+
// NVENC fails if there is no NVENC hardware support.
|
|
212
|
+
bool allowFail = module == "obs-nvenc";
|
|
213
|
+
load_module(modulePath.c_str(), moduleDataPath.c_str(), allowFail);
|
|
203
214
|
}
|
|
204
215
|
|
|
205
216
|
obs_post_load_modules();
|
|
@@ -214,168 +225,119 @@ void ObsInterface::init_obs(const std::string& distPath) {
|
|
|
214
225
|
void ObsInterface::create_output() {
|
|
215
226
|
blog(LOG_INFO, "Create outputs");
|
|
216
227
|
|
|
217
|
-
|
|
218
|
-
|
|
228
|
+
const char* type = buffering ? "replay_buffer" : "ffmpeg_muxer";
|
|
229
|
+
const char* name = buffering ? "Buffer Output" : "File Output";
|
|
219
230
|
|
|
220
|
-
if (
|
|
221
|
-
blog(
|
|
222
|
-
|
|
231
|
+
if (output) {
|
|
232
|
+
blog(LOG_DEBUG, "Releasing existing output");
|
|
233
|
+
obs_output_release(output);
|
|
223
234
|
}
|
|
224
235
|
|
|
225
|
-
blog(LOG_INFO, "Creating
|
|
226
|
-
|
|
236
|
+
blog(LOG_INFO, "Creating replay buffer output");
|
|
237
|
+
output = obs_output_create(type, name, NULL, NULL);
|
|
227
238
|
|
|
228
|
-
if (!
|
|
229
|
-
blog(LOG_ERROR, "Failed to create
|
|
230
|
-
throw std::runtime_error("Failed to create
|
|
239
|
+
if (!output) {
|
|
240
|
+
blog(LOG_ERROR, "Failed to create output!");
|
|
241
|
+
throw std::runtime_error("Failed to create output!");
|
|
231
242
|
}
|
|
232
243
|
|
|
233
|
-
obs_data_t *
|
|
234
|
-
blog(LOG_INFO, "Set replay_buffer settings");
|
|
235
|
-
obs_data_set_int(buffer_settings, "max_time_sec", 60);
|
|
236
|
-
obs_data_set_int(buffer_settings, "max_size_mb", 1024);
|
|
237
|
-
obs_data_set_string(buffer_settings, "directory", recording_path.c_str());
|
|
238
|
-
obs_data_set_string(buffer_settings, "format", "%CCYY-%MM-%DD %hh-%mm-%ss");
|
|
239
|
-
obs_data_set_string(buffer_settings, "extension", "mp4");
|
|
240
|
-
obs_output_update(buffer_output, buffer_settings);
|
|
241
|
-
obs_data_release(buffer_settings);
|
|
244
|
+
obs_data_t *settings = obs_data_create();
|
|
242
245
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
246
|
+
if (buffering) {
|
|
247
|
+
blog(LOG_INFO, "Set replay buffer settings");
|
|
248
|
+
obs_data_set_int(settings, "max_time_sec", 60);
|
|
249
|
+
obs_data_set_int(settings, "max_size_mb", 1024);
|
|
250
|
+
obs_data_set_string(settings, "directory", recording_path.c_str());
|
|
251
|
+
obs_data_set_string(settings, "format", "%CCYY-%MM-%DD %hh-%mm-%ss");
|
|
252
|
+
obs_data_set_string(settings, "extension", "mp4");
|
|
253
|
+
} else {
|
|
254
|
+
blog(LOG_INFO, "Set ffmpeg_muxer settings");
|
|
255
|
+
// Need to specify the exact path for ffmpeg_muxer. We will write this again at start recording.
|
|
256
|
+
std::string filename = recording_path + "\\" + get_current_date_time() + ".mp4";
|
|
257
|
+
obs_data_set_string(settings, "path", filename.c_str());
|
|
258
|
+
unbuffered_output_filename = filename;
|
|
259
|
+
}
|
|
253
260
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
connect_signal_handlers(
|
|
261
|
+
obs_output_update(output, settings);
|
|
262
|
+
obs_data_release(settings);
|
|
263
|
+
connect_signal_handlers(output);
|
|
257
264
|
}
|
|
258
265
|
|
|
259
266
|
void ObsInterface::setRecordingDir(const std::string& recordingPath) {
|
|
260
|
-
blog(LOG_INFO, "Set recording directory");
|
|
261
|
-
// TODO make this work for file output also.
|
|
262
|
-
|
|
263
|
-
obs_output_t *output = buffering ? buffer_output : file_output;
|
|
267
|
+
blog(LOG_INFO, "Set recording directory. Path: %s", recordingPath.c_str());
|
|
264
268
|
|
|
265
|
-
if (!output) {
|
|
266
|
-
blog(LOG_ERROR, "No output to update recording directory");
|
|
267
|
-
throw std::runtime_error("Output not initialized");
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// check its not active
|
|
271
269
|
if (obs_output_active(output)) {
|
|
272
270
|
blog(LOG_ERROR, "Output is active, cannot update recording path");
|
|
273
271
|
throw std::runtime_error("Output is active, cannot update recording path");
|
|
274
272
|
}
|
|
275
273
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (!settings) {
|
|
279
|
-
blog(LOG_ERROR, "Failed to get output settings");
|
|
280
|
-
throw std::runtime_error("Failed to get output settings");
|
|
281
|
-
}
|
|
274
|
+
recording_path = recordingPath;
|
|
275
|
+
create_output();
|
|
282
276
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
obs_data_release(settings);
|
|
277
|
+
create_video_encoders();
|
|
278
|
+
create_audio_encoders();
|
|
286
279
|
}
|
|
287
280
|
|
|
288
281
|
void ObsInterface::create_video_encoders() {
|
|
289
282
|
blog(LOG_INFO, "Set video encoder: %s", video_encoder_id.c_str());
|
|
290
283
|
|
|
291
|
-
if (
|
|
284
|
+
if (video_encoder) {
|
|
292
285
|
blog(LOG_DEBUG, "Releasing file video encoder");
|
|
293
|
-
obs_encoder_release(
|
|
294
|
-
|
|
286
|
+
obs_encoder_release(video_encoder);
|
|
287
|
+
video_encoder = nullptr;
|
|
295
288
|
}
|
|
296
289
|
|
|
297
|
-
|
|
290
|
+
video_encoder = obs_video_encoder_create(
|
|
298
291
|
video_encoder_id.c_str(),
|
|
299
292
|
"noobs_file_encoder",
|
|
300
293
|
video_encoder_settings,
|
|
301
294
|
NULL
|
|
302
295
|
);
|
|
303
296
|
|
|
304
|
-
if (!
|
|
297
|
+
if (!video_encoder) {
|
|
305
298
|
blog(LOG_ERROR, "Failed to create video encoder!");
|
|
306
299
|
throw std::runtime_error("Failed to create video encoder!");
|
|
307
300
|
}
|
|
308
301
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
obs_encoder_release(buffer_video_encoder);
|
|
312
|
-
buffer_video_encoder = nullptr;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
buffer_video_encoder = obs_video_encoder_create(
|
|
316
|
-
video_encoder_id.c_str(),
|
|
317
|
-
"noobs_buffer_encoder",
|
|
318
|
-
video_encoder_settings,
|
|
319
|
-
NULL
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
if (!buffer_video_encoder) {
|
|
323
|
-
blog(LOG_ERROR, "Failed to create buffer video encoder!");
|
|
324
|
-
throw std::runtime_error("Failed to create buffer video encoder!");
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
obs_output_set_video_encoder(file_output, file_video_encoder);
|
|
328
|
-
obs_output_set_video_encoder(buffer_output, buffer_video_encoder);
|
|
329
|
-
|
|
330
|
-
obs_encoder_set_video(file_video_encoder, obs_get_video());
|
|
331
|
-
obs_encoder_set_video(buffer_video_encoder, obs_get_video());
|
|
302
|
+
obs_output_set_video_encoder(output, video_encoder);
|
|
303
|
+
obs_encoder_set_video(video_encoder, obs_get_video());
|
|
332
304
|
}
|
|
333
305
|
|
|
334
306
|
void ObsInterface::create_audio_encoders() {
|
|
335
307
|
blog(LOG_INFO, "Create audio encoder");
|
|
336
308
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
// if (audio_encoder) {
|
|
343
|
-
// blog(LOG_DEBUG, "Releasing audio encoder");
|
|
344
|
-
// obs_encoder_release(audio_encoder);
|
|
345
|
-
// audio_encoder = nullptr;
|
|
346
|
-
// }
|
|
309
|
+
if (audio_encoder) {
|
|
310
|
+
blog(LOG_DEBUG, "Releasing audio encoder");
|
|
311
|
+
obs_encoder_release(audio_encoder);
|
|
312
|
+
audio_encoder = nullptr;
|
|
313
|
+
}
|
|
347
314
|
|
|
348
|
-
|
|
315
|
+
audio_encoder = obs_audio_encoder_create(
|
|
316
|
+
"ffmpeg_aac",
|
|
317
|
+
"aac_file",
|
|
318
|
+
NULL,
|
|
319
|
+
0,
|
|
320
|
+
NULL
|
|
321
|
+
);
|
|
349
322
|
|
|
350
|
-
if (!
|
|
323
|
+
if (!audio_encoder) {
|
|
351
324
|
blog(LOG_ERROR, "Failed to create audio encoder!");
|
|
352
325
|
throw std::runtime_error("Failed to create audio encoder!");
|
|
353
326
|
}
|
|
354
327
|
|
|
355
|
-
buffer_audio_encoder = obs_audio_encoder_create("ffmpeg_aac", "aac_buffer", NULL, 0, NULL);
|
|
356
|
-
|
|
357
|
-
if (!buffer_audio_encoder) {
|
|
358
|
-
blog(LOG_ERROR, "Failed to create buffer audio encoder!");
|
|
359
|
-
throw std::runtime_error("Failed to create buffer audio encoder!");
|
|
360
|
-
}
|
|
361
|
-
|
|
362
328
|
blog(LOG_INFO, "Set audio encoder settings");
|
|
363
329
|
obs_data_t *aenc_settings = obs_data_create();
|
|
364
330
|
obs_data_set_int(aenc_settings, "bitrate", 128);
|
|
365
|
-
obs_encoder_update(
|
|
366
|
-
obs_encoder_update(buffer_audio_encoder, aenc_settings);
|
|
331
|
+
obs_encoder_update(audio_encoder, aenc_settings);
|
|
367
332
|
obs_data_release(aenc_settings);
|
|
368
333
|
|
|
369
|
-
obs_output_set_audio_encoder(
|
|
370
|
-
obs_encoder_set_audio(
|
|
371
|
-
|
|
372
|
-
obs_output_set_audio_encoder(buffer_output, buffer_audio_encoder, 0);
|
|
373
|
-
obs_encoder_set_audio(buffer_audio_encoder, obs_get_audio());
|
|
334
|
+
obs_output_set_audio_encoder(output, audio_encoder, 0);
|
|
335
|
+
obs_encoder_set_audio(audio_encoder, obs_get_audio());
|
|
374
336
|
}
|
|
375
337
|
|
|
376
338
|
void ObsInterface::create_scene() {
|
|
377
339
|
blog(LOG_INFO, "Create scene");
|
|
378
|
-
scene = obs_scene_create("
|
|
340
|
+
scene = obs_scene_create("Base Scene");
|
|
379
341
|
|
|
380
342
|
if (!scene) {
|
|
381
343
|
blog(LOG_ERROR, "Failed to create scene!");
|
|
@@ -414,7 +376,7 @@ void ObsInterface::volmeter_callback(void *data,
|
|
|
414
376
|
self->jscb.NonBlockingCall(sd, call_jscb);
|
|
415
377
|
}
|
|
416
378
|
|
|
417
|
-
|
|
379
|
+
std::string ObsInterface::createSource(std::string name, std::string type) {
|
|
418
380
|
blog(LOG_INFO, "Create source: %s of type %s", name.c_str(), type.c_str());
|
|
419
381
|
|
|
420
382
|
obs_source_t *source = obs_source_create(
|
|
@@ -429,32 +391,59 @@ void ObsInterface::createSource(std::string name, std::string type) {
|
|
|
429
391
|
throw std::runtime_error("Failed to create source!");
|
|
430
392
|
}
|
|
431
393
|
|
|
432
|
-
if
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
} else if (type == AUDIO_INPUT) {
|
|
436
|
-
blog(LOG_INFO, "Setting input volume for source: %s to %d", name.c_str(), input_volume);
|
|
437
|
-
obs_source_set_volume(source, input_volume);
|
|
438
|
-
} else if (type == AUDIO_PROCESS) {
|
|
439
|
-
blog(LOG_INFO, "Setting process volume for source: %s to %d", name.c_str(), process_volume);
|
|
440
|
-
obs_source_set_volume(source, process_volume);
|
|
441
|
-
}
|
|
394
|
+
// The name might not match what we asked for if there is a duplicate.
|
|
395
|
+
// So pass it back to the client to avoid potential for a mismatch.
|
|
396
|
+
std::string real_name = obs_source_get_name(source);
|
|
442
397
|
|
|
443
398
|
if (type == AUDIO_OUTPUT || type == AUDIO_INPUT || type == AUDIO_PROCESS) {
|
|
444
|
-
blog(LOG_INFO, "Creating volmeter for source: %s",
|
|
399
|
+
blog(LOG_INFO, "Creating volmeter for source: %s", real_name.c_str());
|
|
445
400
|
|
|
446
401
|
obs_volmeter_t *volmeter = obs_volmeter_create(OBS_FADER_CUBIC);
|
|
447
402
|
obs_volmeter_attach_source(volmeter, source);
|
|
448
403
|
|
|
449
|
-
SignalContext* ctx = new SignalContext{ this,
|
|
404
|
+
SignalContext* ctx = new SignalContext{ this, real_name }; // TODO don't leak this.
|
|
450
405
|
obs_volmeter_add_callback(volmeter, volmeter_callback, ctx);
|
|
451
406
|
|
|
452
407
|
// Store the volmeter in the volmeters map.
|
|
453
|
-
volmeters[
|
|
408
|
+
volmeters[real_name] = volmeter;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (type == AUDIO_INPUT && force_mono) {
|
|
412
|
+
blog(LOG_INFO, "Setting force mono for new source: %s", real_name.c_str());
|
|
413
|
+
uint32_t flags = obs_source_get_flags(source);
|
|
414
|
+
obs_source_set_flags(source, flags | OBS_SOURCE_FLAG_FORCE_MONO);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (type == AUDIO_INPUT && audio_suppression) {
|
|
418
|
+
blog(LOG_INFO, "Setting up filter for new source: %s", real_name.c_str());
|
|
419
|
+
std::string filter_name = "Filter for " + real_name;
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
obs_source_t *filter = obs_source_create(
|
|
423
|
+
"noise_suppress_filter_v2",
|
|
424
|
+
filter_name.c_str(),
|
|
425
|
+
nullptr, // Defaults are sensible.
|
|
426
|
+
nullptr
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
if (!filter) {
|
|
430
|
+
blog(LOG_ERROR, "Failed to create filter for source: %s", real_name.c_str());
|
|
431
|
+
throw std::runtime_error("Failed to create filter!");
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
filters[real_name] = filter;
|
|
435
|
+
obs_source_filter_add(source, filter);
|
|
454
436
|
}
|
|
455
437
|
|
|
456
438
|
// Store the source in the sources map.
|
|
457
|
-
sources[
|
|
439
|
+
sources[real_name] = source;
|
|
440
|
+
|
|
441
|
+
// Store the dimensions so we can fire a callback if they change.
|
|
442
|
+
uint32_t w = obs_source_get_width(source);
|
|
443
|
+
uint32_t h = obs_source_get_height(source);
|
|
444
|
+
sizes[real_name] = { w, h };
|
|
445
|
+
|
|
446
|
+
return real_name;
|
|
458
447
|
}
|
|
459
448
|
|
|
460
449
|
void ObsInterface::deleteSource(std::string name) {
|
|
@@ -477,14 +466,27 @@ void ObsInterface::deleteSource(std::string name) {
|
|
|
477
466
|
auto it = sources.find(name);
|
|
478
467
|
|
|
479
468
|
if (it == sources.end()) {
|
|
480
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
469
|
+
blog(LOG_WARNING, "Source %s not found when deleting", name.c_str());
|
|
481
470
|
return;
|
|
482
471
|
}
|
|
483
472
|
|
|
484
473
|
obs_source_t* source = it->second;
|
|
474
|
+
|
|
475
|
+
// Remove and release any filters.
|
|
476
|
+
auto filter_it = filters.find(name);
|
|
477
|
+
|
|
478
|
+
if (filter_it != filters.end()) {
|
|
479
|
+
obs_source_t* filter = filter_it->second;
|
|
480
|
+
obs_source_filter_remove(source, filter);
|
|
481
|
+
obs_source_release(filter);
|
|
482
|
+
filters.erase(name);
|
|
483
|
+
blog(LOG_INFO, "Filter deleted for source: %s", name.c_str());
|
|
484
|
+
}
|
|
485
|
+
|
|
485
486
|
obs_source_remove(source); // ???
|
|
486
487
|
obs_source_release(source);
|
|
487
488
|
sources.erase(name);
|
|
489
|
+
sizes.erase(name);
|
|
488
490
|
blog(LOG_INFO, "Source deleted: %s", name.c_str());
|
|
489
491
|
}
|
|
490
492
|
|
|
@@ -494,7 +496,7 @@ obs_data_t* ObsInterface::getSourceSettings(std::string name) {
|
|
|
494
496
|
auto it = sources.find(name);
|
|
495
497
|
|
|
496
498
|
if (it == sources.end()) {
|
|
497
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
499
|
+
blog(LOG_WARNING, "Source %s not found when getting settings", name.c_str());
|
|
498
500
|
throw std::runtime_error("Source not found!");
|
|
499
501
|
}
|
|
500
502
|
|
|
@@ -515,13 +517,27 @@ void ObsInterface::setSourceSettings(std::string name, obs_data_t* settings) {
|
|
|
515
517
|
auto it = sources.find(name);
|
|
516
518
|
|
|
517
519
|
if (it == sources.end()) {
|
|
518
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
520
|
+
blog(LOG_WARNING, "Source %s not found when setting settings", name.c_str());
|
|
519
521
|
throw std::runtime_error("Source not found!");
|
|
520
522
|
}
|
|
521
523
|
|
|
522
524
|
obs_source_t* source = it->second;
|
|
523
|
-
|
|
524
525
|
obs_source_update(source, settings);
|
|
526
|
+
|
|
527
|
+
// If this is an audio source, it may have an attached volmeter.
|
|
528
|
+
auto vol_it = volmeters.find(name);
|
|
529
|
+
|
|
530
|
+
if (vol_it != volmeters.end()) {
|
|
531
|
+
// Rebind it. This avoids leaving it attached to stale audio stream
|
|
532
|
+
// in the event of a device change.
|
|
533
|
+
blog(LOG_INFO, "Rebinding volmeter for source: %s", name.c_str());
|
|
534
|
+
obs_volmeter_t* volmeter = vol_it->second;
|
|
535
|
+
obs_volmeter_attach_source(volmeter, source);
|
|
536
|
+
|
|
537
|
+
// Flush the volmeter: send a zero signal in-case it never triggers any
|
|
538
|
+
// more callbacks. That can happen on selecting a device with no audio.
|
|
539
|
+
zeroVolmeter(name);
|
|
540
|
+
}
|
|
525
541
|
}
|
|
526
542
|
|
|
527
543
|
obs_properties_t* ObsInterface::getSourceProperties(std::string name) {
|
|
@@ -529,7 +545,7 @@ obs_properties_t* ObsInterface::getSourceProperties(std::string name) {
|
|
|
529
545
|
auto it = sources.find(name);
|
|
530
546
|
|
|
531
547
|
if (it == sources.end()) {
|
|
532
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
548
|
+
blog(LOG_WARNING, "Source %s not found when getting properties", name.c_str());
|
|
533
549
|
throw std::runtime_error("Source not found!");
|
|
534
550
|
}
|
|
535
551
|
|
|
@@ -671,15 +687,30 @@ void draw_callback(void* data, uint32_t cx, uint32_t cy) {
|
|
|
671
687
|
// Renders the scene now the graphics context is setup.
|
|
672
688
|
obs_render_main_texture();
|
|
673
689
|
|
|
674
|
-
// Draw boxes around sources.
|
|
675
|
-
obs_scene_t* scene = obs_get_scene_by_name("WCR Scene");
|
|
690
|
+
// Draw boxes around sources, if enabled.
|
|
676
691
|
if (obsInterface->getDrawSourceOutlineEnabled()) {
|
|
692
|
+
obs_scene_t* scene = obs_get_scene_by_name("Base Scene");
|
|
677
693
|
obs_scene_enum_items(scene, draw_source_outline, NULL);
|
|
694
|
+
obs_scene_release(scene);
|
|
678
695
|
}
|
|
679
|
-
obs_scene_release(scene);
|
|
680
696
|
|
|
681
697
|
gs_projection_pop();
|
|
682
698
|
gs_viewport_pop();
|
|
699
|
+
|
|
700
|
+
// Iterate over the sources and check for changes to size.
|
|
701
|
+
for (const auto& [name, source] : obsInterface->sources) {
|
|
702
|
+
SourceSize last = obsInterface->sizes[name];
|
|
703
|
+
|
|
704
|
+
uint32_t w = obs_source_get_width(source);
|
|
705
|
+
uint32_t h = obs_source_get_height(source);
|
|
706
|
+
|
|
707
|
+
if (w != last.width || h != last.height) {
|
|
708
|
+
blog(LOG_INFO, "Source %s changed size from (%d x %d) to (%d x %d)",
|
|
709
|
+
name.c_str(), last.width, last.height, w, h);
|
|
710
|
+
obsInterface->sourceCallback(name);
|
|
711
|
+
obsInterface->sizes[name] = { w, h };
|
|
712
|
+
}
|
|
713
|
+
}
|
|
683
714
|
}
|
|
684
715
|
|
|
685
716
|
void ObsInterface::initPreview(HWND parent) {
|
|
@@ -733,7 +764,7 @@ void ObsInterface::initPreview(HWND parent) {
|
|
|
733
764
|
}
|
|
734
765
|
|
|
735
766
|
void ObsInterface::configurePreview(int x, int y, int width, int height) {
|
|
736
|
-
blog(LOG_INFO, "ObsInterface::
|
|
767
|
+
blog(LOG_INFO, "ObsInterface::configurePreview");
|
|
737
768
|
|
|
738
769
|
if (!preview_hwnd || !display) {
|
|
739
770
|
blog(LOG_ERROR, "Preview window not initialized");
|
|
@@ -829,7 +860,6 @@ bool ObsInterface::getDrawSourceOutlineEnabled() {
|
|
|
829
860
|
ObsInterface::ObsInterface(
|
|
830
861
|
const std::string& distPath,
|
|
831
862
|
const std::string& logPath,
|
|
832
|
-
const std::string& recordingPath,
|
|
833
863
|
Napi::ThreadSafeFunction cb
|
|
834
864
|
) {
|
|
835
865
|
// Setup logs first so we have logs for the initialization.
|
|
@@ -841,19 +871,16 @@ ObsInterface::ObsInterface(
|
|
|
841
871
|
|
|
842
872
|
// Setup callback function.
|
|
843
873
|
jscb = cb;
|
|
844
|
-
recording_path = recordingPath;
|
|
845
874
|
|
|
875
|
+
// Contexts for signal callbacks.
|
|
846
876
|
starting_ctx = new SignalContext{ this, "starting" };
|
|
847
877
|
start_ctx = new SignalContext{ this, "start" };
|
|
848
878
|
stopping_ctx = new SignalContext{ this, "stopping" };
|
|
849
879
|
stop_ctx = new SignalContext{ this, "stop" };
|
|
850
880
|
|
|
851
881
|
// Create the resources we rely on.
|
|
852
|
-
create_output();
|
|
853
882
|
create_scene();
|
|
854
|
-
|
|
855
|
-
video_encoder_id = "obs_x264";
|
|
856
|
-
video_encoder_settings = obs_data_create();
|
|
883
|
+
create_output();
|
|
857
884
|
create_video_encoders();
|
|
858
885
|
create_audio_encoders();
|
|
859
886
|
}
|
|
@@ -878,6 +905,17 @@ ObsInterface::~ObsInterface() {
|
|
|
878
905
|
for (auto& kv : sources) {
|
|
879
906
|
std::string name = kv.first;
|
|
880
907
|
obs_source_t* source = kv.second;
|
|
908
|
+
|
|
909
|
+
auto filter_it = filters.find(name);
|
|
910
|
+
|
|
911
|
+
if (filter_it != filters.end()) {
|
|
912
|
+
obs_source_t* filter = filter_it->second;
|
|
913
|
+
obs_source_filter_remove(source, filter);
|
|
914
|
+
obs_source_release(filter);
|
|
915
|
+
filters.erase(name);
|
|
916
|
+
blog(LOG_INFO, "Filter removed for source: %s on shutdown", name.c_str());
|
|
917
|
+
}
|
|
918
|
+
|
|
881
919
|
blog(LOG_DEBUG, "Releasing source: %s", name.c_str());
|
|
882
920
|
obs_source_release(source);
|
|
883
921
|
sources.erase(name);
|
|
@@ -888,24 +926,14 @@ ObsInterface::~ObsInterface() {
|
|
|
888
926
|
obs_scene_release(scene);
|
|
889
927
|
}
|
|
890
928
|
|
|
891
|
-
if (
|
|
892
|
-
if (obs_output_active(
|
|
929
|
+
if (output) {
|
|
930
|
+
if (obs_output_active(output)) {
|
|
893
931
|
blog(LOG_DEBUG, "Force stopping output");
|
|
894
|
-
obs_output_force_stop(
|
|
932
|
+
obs_output_force_stop(output);
|
|
895
933
|
}
|
|
896
934
|
|
|
897
935
|
blog(LOG_DEBUG, "Releasing output");
|
|
898
|
-
obs_output_release(
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
if (file_output) {
|
|
902
|
-
if (obs_output_active(file_output)) {
|
|
903
|
-
blog(LOG_DEBUG, "Force stopping output");
|
|
904
|
-
obs_output_force_stop(file_output);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
blog(LOG_DEBUG, "Releasing output");
|
|
908
|
-
obs_output_release(file_output);
|
|
936
|
+
obs_output_release(output);
|
|
909
937
|
}
|
|
910
938
|
|
|
911
939
|
// if (video_encoder) {
|
|
@@ -927,16 +955,14 @@ ObsInterface::~ObsInterface() {
|
|
|
927
955
|
}
|
|
928
956
|
}
|
|
929
957
|
|
|
930
|
-
|
|
931
|
-
obs_output_t* output = buffering ? buffer_output : file_output;
|
|
932
|
-
|
|
958
|
+
void ObsInterface::setBuffering(bool value) {
|
|
933
959
|
if (obs_output_active(output)) {
|
|
934
960
|
blog(LOG_ERROR, "Cannot change buffering state while output is active");
|
|
935
|
-
|
|
961
|
+
throw new std::runtime_error("Cannot change buffering state while output is active");
|
|
936
962
|
}
|
|
937
963
|
|
|
938
964
|
buffering = value;
|
|
939
|
-
|
|
965
|
+
create_output();
|
|
940
966
|
}
|
|
941
967
|
|
|
942
968
|
void ObsInterface::startBuffering() {
|
|
@@ -947,8 +973,6 @@ void ObsInterface::startBuffering() {
|
|
|
947
973
|
throw std::runtime_error("Buffering is not enabled!");
|
|
948
974
|
}
|
|
949
975
|
|
|
950
|
-
obs_output_t* output = buffer_output;
|
|
951
|
-
|
|
952
976
|
if (!output) {
|
|
953
977
|
blog(LOG_ERROR, "Output is not initialized!");
|
|
954
978
|
throw std::runtime_error("Output is not initialized!");
|
|
@@ -973,7 +997,11 @@ void ObsInterface::startBuffering() {
|
|
|
973
997
|
|
|
974
998
|
void ObsInterface::startRecording(int offset) {
|
|
975
999
|
blog(LOG_INFO, "ObsInterface::startRecording enter");
|
|
976
|
-
|
|
1000
|
+
|
|
1001
|
+
if (recording_path == "") {
|
|
1002
|
+
blog(LOG_ERROR, "Recording path is not set");
|
|
1003
|
+
throw std::runtime_error("Recording path is not set");
|
|
1004
|
+
}
|
|
977
1005
|
|
|
978
1006
|
if (buffering) {
|
|
979
1007
|
bool is_active = obs_output_active(output);
|
|
@@ -992,10 +1020,10 @@ void ObsInterface::startRecording(int offset) {
|
|
|
992
1020
|
calldata_free(&cd);
|
|
993
1021
|
|
|
994
1022
|
if (!success) {
|
|
1023
|
+
blog(LOG_ERROR, "Failed to call convert procedure handler");
|
|
995
1024
|
throw std::runtime_error("Failed to call convert procedure handler");
|
|
996
1025
|
}
|
|
997
1026
|
} else {
|
|
998
|
-
|
|
999
1027
|
obs_data_t *ffmpeg_settings = obs_data_create();
|
|
1000
1028
|
std::string filename = recording_path + "\\" + get_current_date_time() + ".mp4";
|
|
1001
1029
|
obs_data_set_string(ffmpeg_settings, "path", filename.c_str());
|
|
@@ -1027,7 +1055,6 @@ void ObsInterface::startRecording(int offset) {
|
|
|
1027
1055
|
|
|
1028
1056
|
void ObsInterface::stopRecording() {
|
|
1029
1057
|
blog(LOG_INFO, "ObsInterface::stopRecording enter");
|
|
1030
|
-
obs_output_t* output = buffering ? buffer_output : file_output;
|
|
1031
1058
|
bool is_active = obs_output_active(output);
|
|
1032
1059
|
|
|
1033
1060
|
if (!is_active) {
|
|
@@ -1041,7 +1068,6 @@ void ObsInterface::stopRecording() {
|
|
|
1041
1068
|
|
|
1042
1069
|
void ObsInterface::forceStopRecording() {
|
|
1043
1070
|
blog(LOG_INFO, "ObsInterface::forceStopRecording enter");
|
|
1044
|
-
obs_output_t* output = buffering ? buffer_output : file_output;
|
|
1045
1071
|
bool is_active = obs_output_active(output);
|
|
1046
1072
|
|
|
1047
1073
|
if (!is_active) {
|
|
@@ -1058,7 +1084,6 @@ std::string ObsInterface::getLastRecording() {
|
|
|
1058
1084
|
calldata cd;
|
|
1059
1085
|
calldata_init(&cd);
|
|
1060
1086
|
|
|
1061
|
-
obs_output_t* output = buffering ? buffer_output : file_output;
|
|
1062
1087
|
proc_handler_t *ph = obs_output_get_proc_handler(output);
|
|
1063
1088
|
|
|
1064
1089
|
const char* type = obs_output_get_id(output);
|
|
@@ -1092,7 +1117,7 @@ void ObsInterface::addSourceToScene(std::string name) {
|
|
|
1092
1117
|
auto it = sources.find(name);
|
|
1093
1118
|
|
|
1094
1119
|
if (it == sources.end()) {
|
|
1095
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
1120
|
+
blog(LOG_WARNING, "Source %s not found when adding to scene", name.c_str());
|
|
1096
1121
|
throw std::runtime_error("Source not found!");
|
|
1097
1122
|
}
|
|
1098
1123
|
|
|
@@ -1129,7 +1154,7 @@ void ObsInterface::getSourcePos(std::string name, vec2* pos, vec2* size, vec2* s
|
|
|
1129
1154
|
auto it = sources.find(name);
|
|
1130
1155
|
|
|
1131
1156
|
if (it == sources.end()) {
|
|
1132
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
1157
|
+
blog(LOG_WARNING, "Source %s not found when getting source position", name.c_str());
|
|
1133
1158
|
throw std::runtime_error("Source not found!");
|
|
1134
1159
|
}
|
|
1135
1160
|
|
|
@@ -1184,8 +1209,13 @@ std::vector<std::string> ObsInterface::listAvailableVideoEncoders()
|
|
|
1184
1209
|
}
|
|
1185
1210
|
|
|
1186
1211
|
void ObsInterface::setVideoEncoder(std::string id, obs_data_t* settings) {
|
|
1187
|
-
|
|
1212
|
+
if (obs_output_active(output)) {
|
|
1213
|
+
blog(LOG_WARNING, "Cannot change video encoder while output is active");
|
|
1214
|
+
throw new std::runtime_error("Output is active when trying to change encoder");
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1188
1217
|
video_encoder_id = id;
|
|
1218
|
+
obs_data_release(video_encoder_settings);
|
|
1189
1219
|
video_encoder_settings = settings;
|
|
1190
1220
|
create_video_encoders();
|
|
1191
1221
|
}
|
|
@@ -1197,7 +1227,7 @@ void ObsInterface::setMuteAudioInputs(bool mute) {
|
|
|
1197
1227
|
obs_source_t* source = kv.second;
|
|
1198
1228
|
|
|
1199
1229
|
if (!source) {
|
|
1200
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
1230
|
+
blog(LOG_WARNING, "Source %s not found when muting audio inputs", name.c_str());
|
|
1201
1231
|
continue;
|
|
1202
1232
|
}
|
|
1203
1233
|
|
|
@@ -1209,70 +1239,132 @@ void ObsInterface::setMuteAudioInputs(bool mute) {
|
|
|
1209
1239
|
}
|
|
1210
1240
|
}
|
|
1211
1241
|
|
|
1212
|
-
void ObsInterface::
|
|
1213
|
-
blog(LOG_INFO, "Setting
|
|
1214
|
-
output_volume = volume;
|
|
1242
|
+
void ObsInterface::setSourceVolume(std::string name, float volume) {
|
|
1243
|
+
blog(LOG_INFO, "Setting source %s volume to %f", name.c_str(), volume);
|
|
1215
1244
|
|
|
1216
|
-
|
|
1217
|
-
const std::string& name = kv.first;
|
|
1218
|
-
obs_source_t* source = kv.second;
|
|
1245
|
+
auto it = sources.find(name);
|
|
1219
1246
|
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1247
|
+
if (it == sources.end()) {
|
|
1248
|
+
blog(LOG_WARNING, "Source %s not found when setting volume", name.c_str());
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1224
1251
|
|
|
1225
|
-
|
|
1252
|
+
obs_source_t* source = it->second;
|
|
1253
|
+
const char* type = obs_source_get_id(source);
|
|
1254
|
+
|
|
1255
|
+
bool audio =
|
|
1256
|
+
strcmp(type, AUDIO_OUTPUT) == 0 ||
|
|
1257
|
+
strcmp(type, AUDIO_INPUT) == 0 ||
|
|
1258
|
+
strcmp(type, AUDIO_PROCESS) == 0;
|
|
1226
1259
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1260
|
+
if (!audio) {
|
|
1261
|
+
blog(LOG_WARNING, "Source %s is not a valid audio source", name.c_str());
|
|
1262
|
+
return;
|
|
1230
1263
|
}
|
|
1264
|
+
|
|
1265
|
+
obs_source_set_volume(source, volume);
|
|
1231
1266
|
}
|
|
1232
1267
|
|
|
1233
|
-
void ObsInterface::
|
|
1234
|
-
blog(LOG_INFO, "Setting
|
|
1235
|
-
|
|
1268
|
+
void ObsInterface::setVolmeterEnabled(bool enabled) {
|
|
1269
|
+
blog(LOG_INFO, "Setting volmeter enabled: %d", enabled);
|
|
1270
|
+
volmeter_enabled = enabled;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
void ObsInterface::setForceMono(bool enabled) {
|
|
1274
|
+
blog(LOG_INFO, "%s force mono on all input sources", enabled ? "Enabling" : "Disabling");
|
|
1275
|
+
force_mono = enabled;
|
|
1236
1276
|
|
|
1277
|
+
// Loop over existing sources and update the force mono flags.
|
|
1237
1278
|
for (const auto& kv : sources) {
|
|
1238
1279
|
const std::string& name = kv.first;
|
|
1239
1280
|
obs_source_t* source = kv.second;
|
|
1240
1281
|
|
|
1241
1282
|
if (!source) {
|
|
1242
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
1283
|
+
blog(LOG_WARNING, "Source %s not found when setting force mono", name.c_str());
|
|
1243
1284
|
continue;
|
|
1244
1285
|
}
|
|
1245
1286
|
|
|
1246
1287
|
const char* type = obs_source_get_id(source);
|
|
1247
1288
|
|
|
1248
|
-
if (strcmp(type, AUDIO_INPUT)
|
|
1249
|
-
|
|
1289
|
+
if (strcmp(type, AUDIO_INPUT) != 0) {
|
|
1290
|
+
// Force mono is only applicable to microphones, skip other types.
|
|
1291
|
+
continue;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
if (enabled) {
|
|
1295
|
+
blog(LOG_INFO, "Setting force mono flag on source %s", name.c_str());
|
|
1296
|
+
uint32_t flags = obs_source_get_flags(source);
|
|
1297
|
+
obs_source_set_flags(source, flags | OBS_SOURCE_FLAG_FORCE_MONO);
|
|
1298
|
+
} else {
|
|
1299
|
+
blog(LOG_INFO, "Unsetting force mono flag on source %s", name.c_str());
|
|
1300
|
+
uint32_t flags = obs_source_get_flags(source);
|
|
1301
|
+
obs_source_set_flags(source, flags & ~OBS_SOURCE_FLAG_FORCE_MONO);
|
|
1250
1302
|
}
|
|
1251
1303
|
}
|
|
1252
1304
|
}
|
|
1253
1305
|
|
|
1254
|
-
void ObsInterface::
|
|
1255
|
-
blog(LOG_INFO, "
|
|
1256
|
-
|
|
1306
|
+
void ObsInterface::setAudioSuppression(bool enabled) {
|
|
1307
|
+
blog(LOG_INFO, "%s audio suppression on all input devices", enabled ? "Enabling" : "Disabling");
|
|
1308
|
+
audio_suppression = enabled;
|
|
1257
1309
|
|
|
1310
|
+
// Loop over existing sources and add filters to any that need it.
|
|
1258
1311
|
for (const auto& kv : sources) {
|
|
1259
1312
|
const std::string& name = kv.first;
|
|
1260
1313
|
obs_source_t* source = kv.second;
|
|
1261
1314
|
|
|
1262
1315
|
if (!source) {
|
|
1263
|
-
blog(LOG_WARNING, "Source %s not found", name.c_str());
|
|
1316
|
+
blog(LOG_WARNING, "Source %s not found when adding filters", name.c_str());
|
|
1264
1317
|
continue;
|
|
1265
1318
|
}
|
|
1266
1319
|
|
|
1267
1320
|
const char* type = obs_source_get_id(source);
|
|
1268
1321
|
|
|
1269
|
-
if (strcmp(type,
|
|
1270
|
-
|
|
1322
|
+
if (strcmp(type, AUDIO_INPUT) != 0) {
|
|
1323
|
+
// Don't care about non-input sources. This is purely for suppressing
|
|
1324
|
+
// microphone background noise.
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// Check for a filter existing and add or remove it as appropriate.
|
|
1329
|
+
auto filter_it = filters.find(name);
|
|
1330
|
+
|
|
1331
|
+
if (audio_suppression && filter_it == filters.end()) {
|
|
1332
|
+
blog(LOG_INFO, "Setting up filter for source: %s", name.c_str());
|
|
1333
|
+
|
|
1334
|
+
std::string filter_name = "Filter for " + name;
|
|
1335
|
+
|
|
1336
|
+
obs_source_t *filter = obs_source_create(
|
|
1337
|
+
"noise_suppress_filter_v2",
|
|
1338
|
+
filter_name.c_str(),
|
|
1339
|
+
nullptr, // Defaults are sensible.
|
|
1340
|
+
nullptr
|
|
1341
|
+
);
|
|
1342
|
+
|
|
1343
|
+
if (!filter) {
|
|
1344
|
+
blog(LOG_ERROR, "Failed to create filter for source: %s", name.c_str());
|
|
1345
|
+
throw std::runtime_error("Failed to create filter!");
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
filters[name] = filter;
|
|
1349
|
+
obs_source_filter_add(source, filter);
|
|
1350
|
+
} else if (!audio_suppression && filter_it != filters.end()) {
|
|
1351
|
+
blog(LOG_INFO, "Removing filters for source: %s", name.c_str());
|
|
1352
|
+
obs_source_t* filter = filter_it->second;
|
|
1353
|
+
obs_source_filter_remove(source, filter);
|
|
1354
|
+
filters.erase(name);
|
|
1355
|
+
obs_source_release(filter);
|
|
1271
1356
|
}
|
|
1272
1357
|
}
|
|
1273
1358
|
}
|
|
1274
1359
|
|
|
1275
|
-
void ObsInterface::
|
|
1276
|
-
blog(LOG_INFO, "
|
|
1277
|
-
|
|
1278
|
-
|
|
1360
|
+
void ObsInterface::sourceCallback(std::string name) {
|
|
1361
|
+
blog(LOG_INFO, "Source callback triggered for %s", name.c_str());
|
|
1362
|
+
SignalData* sd = new SignalData{ "source", name.c_str(), 0 };
|
|
1363
|
+
jscb.NonBlockingCall(sd, call_jscb);
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
void ObsInterface::zeroVolmeter(std::string name) {
|
|
1367
|
+
blog(LOG_INFO, "Zeroing volmeter for %s", name.c_str());
|
|
1368
|
+
SignalData* sd = new SignalData{ "volmeter", name.c_str(), 0, 0 };
|
|
1369
|
+
jscb.NonBlockingCall(sd, call_jscb);
|
|
1370
|
+
}
|