Skip to content

Commit da21854

Browse files
Implemented dual streaming with the new Enhnaced Broadcasting API
1 parent ce077e2 commit da21854

34 files changed

+1973
-571
lines changed

js/module.d.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ export declare const VideoEncoderFactory: IVideoEncoderFactory;
307307
export declare const ServiceFactory: IServiceFactory;
308308
export declare const SimpleStreamingFactory: ISimpleStreamingFactory;
309309
export declare const AdvancedStreamingFactory: IAdvancedStreamingFactory;
310+
export declare const EnhancedBroadcastingAdvancedStreamingFactory: IEnhancedBroadcastingAdvancedStreamingFactory;
311+
export declare const EnhancedBroadcastingSimpleStreamingFactory: IEnhancedBroadcastingSimpleStreamingFactory;
310312
export declare const DelayFactory: IDelayFactory;
311313
export declare const ReconnectFactory: IReconnectFactory;
312314
export declare const NetworkFactory: INetworkFactory;
@@ -794,12 +796,11 @@ export interface IVideoEncoderFactory {
794796
create(id: string, name: string, settings?: ISettings): IVideoEncoder;
795797
}
796798
export interface IStreaming {
797-
// Video encoder value is ignored when enhancedBroadcasting === true
799+
// Video encoder value is ignored in the Enhanced Broadcasting mode
798800
videoEncoder?: IVideoEncoder;
799801
service: IService;
800802
enforceServiceBitrate: boolean;
801803
enableTwitchVOD: boolean;
802-
enhancedBroadcasting: boolean;
803804
delay: IDelay;
804805
reconnect: IReconnect;
805806
network: INetwork;
@@ -840,6 +841,26 @@ export interface IAdvancedStreamingFactory {
840841
destroy(stream: IAdvancedStreaming): void;
841842
legacySettings: IAdvancedStreaming;
842843
}
844+
export interface IEnhancedBroadcastingAdvancedStreaming extends IAdvancedStreaming {
845+
// If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
846+
// This value should be initialized before the stream start.
847+
additionalVideo?: IVideo,
848+
}
849+
export interface IEnhancedBroadcastingAdvancedStreamingFactory {
850+
create(): IEnhancedBroadcastingAdvancedStreaming;
851+
destroy(stream: IEnhancedBroadcastingAdvancedStreaming): void;
852+
legacySettings: IEnhancedBroadcastingAdvancedStreaming;
853+
}
854+
export interface IEnhancedBroadcastingSimpleStreaming extends ISimpleStreaming {
855+
// If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
856+
// This value should be initialized before the stream start.
857+
additionalVideo?: IVideo,
858+
}
859+
export interface IEnhancedBroadcastingSimpleStreamingFactory {
860+
create(): IEnhancedBroadcastingSimpleStreaming;
861+
destroy(stream: IEnhancedBroadcastingSimpleStreaming): void;
862+
legacySettings: IEnhancedBroadcastingSimpleStreaming;
863+
}
843864
export interface IFileOutput {
844865
path: string;
845866
format: ERecordingFormat;

js/module.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3-
exports.NodeObs = exports.getSourcesSize = exports.createSources = exports.addItems = exports.AdvancedReplayBufferFactory = exports.SimpleReplayBufferFactory = exports.AudioEncoderFactory = exports.AdvancedRecordingFactory = exports.SimpleRecordingFactory = exports.AudioTrackFactory = exports.NetworkFactory = exports.ReconnectFactory = exports.DelayFactory = exports.AdvancedStreamingFactory = exports.SimpleStreamingFactory = exports.ServiceFactory = exports.VideoEncoderFactory = exports.IPC = exports.ModuleFactory = exports.AudioFactory = exports.Audio = exports.FaderFactory = exports.VolmeterFactory = exports.DisplayFactory = exports.TransitionFactory = exports.FilterFactory = exports.SceneFactory = exports.InputFactory = exports.VideoFactory = exports.Video = exports.Global = exports.DefaultPluginPathMac = exports.DefaultPluginDataPath = exports.DefaultPluginPath = exports.DefaultDataPath = exports.DefaultBinPath = exports.DefaultDrawPluginPath = exports.DefaultOpenGLPath = exports.DefaultD3D11Path = void 0;
3+
exports.NodeObs = exports.getSourcesSize = exports.createSources = exports.addItems = exports.AdvancedReplayBufferFactory = exports.SimpleReplayBufferFactory = exports.AudioEncoderFactory = exports.AdvancedRecordingFactory = exports.SimpleRecordingFactory = exports.AudioTrackFactory = exports.NetworkFactory = exports.ReconnectFactory = exports.DelayFactory = exports.AdvancedStreamingFactory = exports.EnhancedBroadcastingSimpleStreamingFactory = exports.EnhancedBroadcastingAdvancedStreamingFactory = exports.SimpleStreamingFactory = exports.ServiceFactory = exports.VideoEncoderFactory = exports.IPC = exports.ModuleFactory = exports.AudioFactory = exports.Audio = exports.FaderFactory = exports.VolmeterFactory = exports.DisplayFactory = exports.TransitionFactory = exports.FilterFactory = exports.SceneFactory = exports.InputFactory = exports.VideoFactory = exports.Video = exports.Global = exports.DefaultPluginPathMac = exports.DefaultPluginDataPath = exports.DefaultPluginPath = exports.DefaultDataPath = exports.DefaultBinPath = exports.DefaultDrawPluginPath = exports.DefaultOpenGLPath = exports.DefaultD3D11Path = void 0;
44
const path = require("path");
55
const fs = require("fs");
66
// Mac- search for optional OSN.app bundle (Chromium requires an app bundle to find obs64 helper apps)
@@ -34,6 +34,8 @@ exports.VideoEncoderFactory = obs.VideoEncoder;
3434
exports.ServiceFactory = obs.Service;
3535
exports.SimpleStreamingFactory = obs.SimpleStreaming;
3636
exports.AdvancedStreamingFactory = obs.AdvancedStreaming;
37+
exports.EnhancedBroadcastingAdvancedStreamingFactory = obs.EnhancedBroadcastingAdvancedStreaming;
38+
exports.EnhancedBroadcastingSimpleStreamingFactory = obs.EnhancedBroadcastingSimpleStreaming;
3739
exports.DelayFactory = obs.Delay;
3840
exports.ReconnectFactory = obs.Reconnect;
3941
exports.NetworkFactory = obs.Network;
@@ -70,7 +72,7 @@ function createSources(sources) {
7072
console.error(`[OSN] Failed to create input for source "${source.name}":`, error instanceof Error ? error.message : error);
7173
return; // Skip the rest of this iteration if input creation fails
7274
}
73-
75+
7476
if (newSource) {
7577
if (newSource.audioMixers) {
7678
newSource.muted = source.muted ?? false;
@@ -80,7 +82,7 @@ function createSources(sources) {
8082
newSource.deinterlaceMode = source.deinterlaceMode;
8183
newSource.deinterlaceFieldOrder = source.deinterlaceFieldOrder;
8284
items.push(newSource);
83-
85+
8486
const filters = source.filters;
8587
if (Array.isArray(filters)) {
8688
filters.forEach(function (filter) {
@@ -90,7 +92,7 @@ function createSources(sources) {
9092
} catch (filterError) {
9193
console.error(`[OSN] Failed to create filter "${filter.name}" for source "${source.name}":`, filterError instanceof Error ? filterError.message : filterError);
9294
}
93-
95+
9496
if (ObsFilter) {
9597
ObsFilter.enabled = filter.enabled ?? true;
9698
newSource.addFilter(ObsFilter);

js/module.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ export const VideoEncoderFactory: IVideoEncoderFactory = obs.VideoEncoder;
392392
export const ServiceFactory: IServiceFactory = obs.Service;
393393
export const SimpleStreamingFactory: ISimpleStreamingFactory = obs.SimpleStreaming;
394394
export const AdvancedStreamingFactory: IAdvancedStreamingFactory = obs.AdvancedStreaming;
395+
export const EnhancedBroadcastingAdvancedStreamingFactory: IEnhancedBroadcastingAdvancedStreamingFactory = obs.EnhancedBroadcastingAdvancedStreaming;
396+
export const EnhancedBroadcastingSimpleStreamingFactory: IEnhancedBroadcastingSimpleStreamingFactory = obs.EnhancedBroadcastingSimpleStreaming;
395397
export const DelayFactory: IDelayFactory = obs.Delay;
396398
export const ReconnectFactory: IReconnectFactory = obs.Reconnect;
397399
export const NetworkFactory: INetworkFactory = obs.Network;
@@ -1705,12 +1707,11 @@ export interface IVideoEncoderFactory {
17051707
}
17061708

17071709
export interface IStreaming {
1708-
// Video encoder value is ignored when enhancedBroadcasting === true
1710+
// Video encoder value is ignored in the Enhanced Broadcasting mode
17091711
videoEncoder?: IVideoEncoder,
17101712
service: IService,
17111713
enforceServiceBitrate: boolean,
17121714
enableTwitchVOD: boolean,
1713-
enhancedBroadcasting: boolean,
17141715
delay: IDelay,
17151716
reconnect: IReconnect,
17161717
network: INetwork,
@@ -1757,6 +1758,30 @@ export interface IAdvancedStreamingFactory {
17571758
legacySettings: IAdvancedStreaming;
17581759
}
17591760

1761+
export interface IEnhancedBroadcastingAdvancedStreaming extends IAdvancedStreaming {
1762+
// If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
1763+
// This value should be initialized before the stream start.
1764+
additionalVideo?: IVideo,
1765+
}
1766+
1767+
export interface IEnhancedBroadcastingAdvancedStreamingFactory {
1768+
create(): IEnhancedBroadcastingAdvancedStreaming;
1769+
destroy(stream: IEnhancedBroadcastingAdvancedStreaming): void;
1770+
legacySettings: IEnhancedBroadcastingAdvancedStreaming;
1771+
}
1772+
1773+
export interface IEnhancedBroadcastingSimpleStreaming extends ISimpleStreaming {
1774+
// If set, the Enhanced Broadcasting stream will be in the Dual Output mode.
1775+
// This value should be initialized before the stream start.
1776+
additionalVideo?: IVideo,
1777+
}
1778+
1779+
export interface IEnhancedBroadcastingSimpleStreamingFactory {
1780+
create(): IEnhancedBroadcastingSimpleStreaming;
1781+
destroy(stream: IEnhancedBroadcastingSimpleStreaming): void;
1782+
legacySettings: IEnhancedBroadcastingSimpleStreaming;
1783+
}
1784+
17601785
export interface IFileOutput {
17611786
path: string,
17621787
format: ERecordingFormat,

obs-studio-client/CMakeLists.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,18 @@ SET(osn-client_SOURCES
9898
"source/audio.cpp"
9999
"source/streaming.hpp"
100100
"source/streaming.cpp"
101+
"source/simple-streaming-base.hpp"
102+
"source/simple-streaming-base.cpp"
101103
"source/simple-streaming.hpp"
102104
"source/simple-streaming.cpp"
105+
"source/advanced-streaming-base.hpp"
106+
"source/advanced-streaming-base.cpp"
103107
"source/advanced-streaming.hpp"
104108
"source/advanced-streaming.cpp"
109+
"source/enhanced-broadcasting-advanced-streaming.hpp"
110+
"source/enhanced-broadcasting-advanced-streaming.cpp"
111+
"source/enhanced-broadcasting-simple-streaming.hpp"
112+
"source/enhanced-broadcasting-simple-streaming.cpp"
105113
"source/worker-signals.hpp"
106114
"source/delay.hpp"
107115
"source/delay.cpp"
@@ -187,7 +195,7 @@ target_link_libraries(${PROJECT_NAME} ${LIBOBS_LIBRARIES})
187195
add_definitions(-DNAPI_VERSION=7)
188196

189197
#Define the OSN_VERSION
190-
add_compile_definitions(OSN_VERSION=\"$ENV{tagartifact}\")
198+
add_compile_definitions(OSN_VERSION=\"$ENV{tagartifact}\")
191199
set_target_properties(
192200
obs_studio_client
193201
PROPERTIES
@@ -235,5 +243,5 @@ install(
235243
TARGETS obs_studio_client
236244
RUNTIME DESTINATION "./" COMPONENT Runtime
237245
LIBRARY DESTINATION "./" COMPONENT Runtime
238-
ARCHIVE DESTINATION "./" COMPONENT Runtime
246+
ARCHIVE DESTINATION "./" COMPONENT Runtime
239247
)
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/******************************************************************************
2+
Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
******************************************************************************/
18+
19+
#include "advanced-streaming-base.hpp"
20+
21+
Napi::Value osn::AdvancedStreamingBase::GetAudioTrack(const Napi::CallbackInfo &info)
22+
{
23+
auto conn = GetConnection(info);
24+
if (!conn)
25+
return info.Env().Undefined();
26+
27+
std::vector<ipc::value> response = conn->call_synchronous_helper("AdvancedStreaming", "GetAudioTrack", {ipc::value(this->uid)});
28+
29+
if (!ValidateResponse(info, response))
30+
return info.Env().Undefined();
31+
32+
return Napi::Number::New(info.Env(), response[1].value_union.ui32);
33+
}
34+
35+
void osn::AdvancedStreamingBase::SetAudioTrack(const Napi::CallbackInfo &info, const Napi::Value &value)
36+
{
37+
auto conn = GetConnection(info);
38+
if (!conn)
39+
return;
40+
41+
conn->call_synchronous_helper("AdvancedStreaming", "SetAudioTrack", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
42+
}
43+
44+
Napi::Value osn::AdvancedStreamingBase::GetTwitchTrack(const Napi::CallbackInfo &info)
45+
{
46+
auto conn = GetConnection(info);
47+
if (!conn)
48+
return info.Env().Undefined();
49+
50+
std::vector<ipc::value> response = conn->call_synchronous_helper("AdvancedStreaming", "GetTwitchTrack", {ipc::value(this->uid)});
51+
52+
if (!ValidateResponse(info, response))
53+
return info.Env().Undefined();
54+
55+
return Napi::Number::New(info.Env(), response[1].value_union.ui32);
56+
}
57+
58+
void osn::AdvancedStreamingBase::SetTwitchTrack(const Napi::CallbackInfo &info, const Napi::Value &value)
59+
{
60+
auto conn = GetConnection(info);
61+
if (!conn)
62+
return;
63+
64+
conn->call_synchronous_helper("AdvancedStreaming", "SetTwitchTrack", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
65+
}
66+
67+
Napi::Value osn::AdvancedStreamingBase::GetRescaling(const Napi::CallbackInfo &info)
68+
{
69+
auto conn = GetConnection(info);
70+
if (!conn)
71+
return info.Env().Undefined();
72+
73+
std::vector<ipc::value> response = conn->call_synchronous_helper("AdvancedStreaming", "GetRescaling", {ipc::value(this->uid)});
74+
75+
if (!ValidateResponse(info, response))
76+
return info.Env().Undefined();
77+
78+
return Napi::Boolean::New(info.Env(), response[1].value_union.ui32);
79+
}
80+
81+
void osn::AdvancedStreamingBase::SetRescaling(const Napi::CallbackInfo &info, const Napi::Value &value)
82+
{
83+
auto conn = GetConnection(info);
84+
if (!conn)
85+
return;
86+
87+
conn->call_synchronous_helper("AdvancedStreaming", "SetRescaling", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
88+
}
89+
90+
Napi::Value osn::AdvancedStreamingBase::GetOutputWidth(const Napi::CallbackInfo &info)
91+
{
92+
auto conn = GetConnection(info);
93+
if (!conn)
94+
return info.Env().Undefined();
95+
96+
std::vector<ipc::value> response = conn->call_synchronous_helper("AdvancedStreaming", "GetOutputWidth", {ipc::value(this->uid)});
97+
98+
if (!ValidateResponse(info, response))
99+
return info.Env().Undefined();
100+
101+
return Napi::Number::New(info.Env(), response[1].value_union.ui32);
102+
}
103+
104+
void osn::AdvancedStreamingBase::SetOutputWidth(const Napi::CallbackInfo &info, const Napi::Value &value)
105+
{
106+
auto conn = GetConnection(info);
107+
if (!conn)
108+
return;
109+
110+
conn->call_synchronous_helper("AdvancedStreaming", "SetOutputWidth", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
111+
}
112+
113+
Napi::Value osn::AdvancedStreamingBase::GetOutputHeight(const Napi::CallbackInfo &info)
114+
{
115+
auto conn = GetConnection(info);
116+
if (!conn)
117+
return info.Env().Undefined();
118+
119+
std::vector<ipc::value> response = conn->call_synchronous_helper("AdvancedStreaming", "GetOutputHeight", {ipc::value(this->uid)});
120+
121+
if (!ValidateResponse(info, response))
122+
return info.Env().Undefined();
123+
124+
return Napi::Number::New(info.Env(), response[1].value_union.ui32);
125+
}
126+
127+
void osn::AdvancedStreamingBase::SetOutputHeight(const Napi::CallbackInfo &info, const Napi::Value &value)
128+
{
129+
auto conn = GetConnection(info);
130+
if (!conn)
131+
return;
132+
133+
conn->call_synchronous_helper("AdvancedStreaming", "SetOutputHeight", {ipc::value(this->uid), ipc::value(value.ToNumber().Uint32Value())});
134+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/******************************************************************************
2+
Copyright (C) 2016-2022 by Streamlabs (General Workings Inc)
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
******************************************************************************/
18+
19+
#pragma once
20+
#include <napi.h>
21+
#include "streaming.hpp"
22+
23+
namespace osn {
24+
25+
class AdvancedStreamingBase : public osn::Streaming {
26+
public:
27+
Napi::Value GetAudioTrack(const Napi::CallbackInfo &info);
28+
void SetAudioTrack(const Napi::CallbackInfo &info, const Napi::Value &value);
29+
Napi::Value GetTwitchTrack(const Napi::CallbackInfo &info);
30+
void SetTwitchTrack(const Napi::CallbackInfo &info, const Napi::Value &value);
31+
Napi::Value GetRescaling(const Napi::CallbackInfo &info);
32+
void SetRescaling(const Napi::CallbackInfo &info, const Napi::Value &value);
33+
Napi::Value GetOutputWidth(const Napi::CallbackInfo &info);
34+
void SetOutputWidth(const Napi::CallbackInfo &info, const Napi::Value &value);
35+
Napi::Value GetOutputHeight(const Napi::CallbackInfo &info);
36+
void SetOutputHeight(const Napi::CallbackInfo &info, const Napi::Value &value);
37+
};
38+
39+
}

0 commit comments

Comments
 (0)