Repository navigation
Expand file tree
/
Copy pathEmptyProfile BRB Engine.cs
More file actions
153 lines (130 loc) · 6.11 KB
/
Copy pathEmptyProfile BRB Engine.cs
File metadata and controls
153 lines (130 loc) · 6.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Twitch.Common.Models.Api;
public class CPHInline
{
private List<int> availableIndices;
private string nextVideoUrl;
private string nextClipInfo;
private double nextClipDuration;
public bool Execute()
{
// Fetch global variables set in Streamer.bot
var scene = CPH.GetGlobalVar<string>("BRBScene", true);
var source = CPH.GetGlobalVar<string>("BRBBrowserSource", true);
var clipCreditsSource = CPH.GetGlobalVar<string>("ClipCreditsSource", true);
var videoPlayerHtml = CPH.GetGlobalVar<string>("VideoPlayerHtml", true);
var nodeServerUrl = CPH.GetGlobalVar<string>("NodeServerUrl", true);
var nodeServerPort = CPH.GetGlobalVar<string>("NodeServerPort", true);
var workingDirectory = CPH.GetGlobalVar<string>("WorkingDirectory", true);
List<ClipData> allClips = JsonConvert.DeserializeObject<List<ClipData>>(CPH.GetGlobalVar<string>("BrbAllClips", true));
// Validate the nodeServerPort, default to 3000 if not set or invalid
if (string.IsNullOrEmpty(nodeServerPort) || !int.TryParse(nodeServerPort, out int port) || port <= 0 || port > 65535)
{
CPH.LogWarn($"Invalid or missing NodeServerPort. Defaulting to port 3000.");
nodeServerPort = "3000";
}
string fullNodeServerUrl = $"http://{nodeServerUrl}:{nodeServerPort}";
CPH.LogWarn("Server URL: " + fullNodeServerUrl);
// Initialize available indices if empty
if (availableIndices == null || availableIndices.Count <= 0)
{
availableIndices = new List<int>();
for (int i = 0; i < allClips.Count; i++)
{
availableIndices.Add(i);
// CPH.LogWarn("All Clips Title: " + allClips[i].Title + " | Index: " + i);
}
}
Random rd = new Random();
// Start fetching the first video URL asynchronously
Task fetchNextVideoTask = FetchNextVideoUrlAsync(allClips, rd, videoPlayerHtml, fullNodeServerUrl, clipCreditsSource, scene, workingDirectory);
// Set OBS scene to BRB scene
CPH.ObsSetScene(scene);
int delayLoop = 0;
while ((delayLoop < 25) && (CPH.ObsGetCurrentScene() != scene))
{
CPH.Wait(100);
delayLoop++;
}
while (CPH.ObsGetCurrentScene() == scene)
{
// Wait for the next video URL to be ready
fetchNextVideoTask.Wait();
if (!string.IsNullOrEmpty(nextVideoUrl))
{
CPH.LogWarn("Setting OBS Browser Source to: " + nextVideoUrl);
CPH.ObsSetBrowserSource(scene, source, nextVideoUrl);
CPH.ObsSetGdiText(scene, clipCreditsSource, nextClipInfo);
}
// Set delay based on the clip's duration + 500ms for safety
int delay = (int)(nextClipDuration * 1000) + 500;
// Fetch the next video URL while the current video is playing
fetchNextVideoTask = FetchNextVideoUrlAsync(allClips, rd, videoPlayerHtml, fullNodeServerUrl, clipCreditsSource, scene, workingDirectory);
int delayLeft = delay;
int delayInterval = 1000;
while (delayLeft > delayInterval)
{
if (CPH.ObsGetCurrentScene() != scene)
{
CPH.ObsSetBrowserSource(scene, source, "about:blank");
CPH.ObsSetGdiText(scene, clipCreditsSource, "");
return true;
}
CPH.Wait(delayInterval);
delayLeft -= delayInterval;
}
CPH.Wait(delayLeft);
CPH.LogWarn("Clip finished");
CPH.ObsSetGdiText(scene, clipCreditsSource, "");
}
CPH.ObsSetBrowserSource(scene, source, "about:blank");
return true;
}
private async Task FetchNextVideoUrlAsync(List<Twitch.Common.Models.Api.ClipData> allClips, Random rd, string videoPlayerHtml, string fullNodeServerUrl, string clipCreditsSource, string scene, string workingDirectory)
{
if (availableIndices.Count > 0)
{
// Select a random clip from the available list
int randIndex = rd.Next(0, availableIndices.Count);
int clipIndex = availableIndices[randIndex];
availableIndices.RemoveAt(randIndex);
var selectedClip = allClips[clipIndex];
// Use the embed URL and add "&parent=localhost" to avoid CORS and SOP restrictions
string embedURL = $"{selectedClip.EmbedUrl}&parent=localhost";
nextClipInfo = '"' + selectedClip.Title + '"' + " by " + selectedClip.CreatorName;
nextClipDuration = selectedClip.Duration; // Capture the duration of the next clip
// Call the Node.js server to fetch the video's source URL
using (HttpClient client = new HttpClient())
{
string requestUrl = $"{fullNodeServerUrl}/get-mp4?url={Uri.EscapeDataString(embedURL)}";
try
{
HttpResponseMessage response = await client.GetAsync(requestUrl);
response.EnsureSuccessStatusCode();
string mp4Url = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(mp4Url))
{
// Use the raw URL & ensure no encoding
var fullVideoPlayerHtml = $"{workingDirectory}\\{videoPlayerHtml}";
nextVideoUrl = $"file:///{fullVideoPlayerHtml}?{mp4Url}";
}
else
{
CPH.LogError("Failed to retrieve the video URL.");
nextVideoUrl = null;
}
}
catch (Exception ex)
{
CPH.LogError("Error calling Node.js server: " + ex.Message);
nextVideoUrl = null;
}
}
}
}
}