Skip to content

Commit 149b05b

Browse files
authored
Merge pull request #113 from viruslox/feature-visionbridge-fixes-3939820217668669565
feat: Chromium Chroma Key, VFR Concat Fixes, and 8-Layer Expansion
2 parents a8a1508 + b43585a commit 149b05b

6 files changed

Lines changed: 89 additions & 30 deletions

File tree

configs/visionbridge.settings.template

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,44 +25,58 @@ input:
2525
bg-color: ""
2626
z1_volume: 100
2727
z1_width: 1920
28+
z1_height: 1080
2829
z1_x: 0
2930
z1_y: 0
3031
z2_active: false
3132
z2_path: "https://example.com/middle"
3233
z2_volume: 100
3334
z2_width: 1920
35+
z2_height: 1080
3436
z2_x: 0
3537
z2_y: 0
3638
z3_active: false
3739
z3_path: "https://example.com/upper"
3840
z3_volume: 100
3941
z3_width: 1920
42+
z3_height: 1080
4043
z3_x: 0
4144
z3_y: 0
4245
z4_active: false
4346
z4_path: ""
4447
z4_volume: 100
4548
z4_width: 1920
49+
z4_height: 1080
4650
z4_x: 0
4751
z4_y: 0
4852
z5_active: false
4953
z5_path: ""
5054
z5_volume: 100
5155
z5_width: 1920
56+
z5_height: 1080
5257
z5_x: 0
5358
z5_y: 0
5459
z6_active: false
5560
z6_path: ""
5661
z6_volume: 100
5762
z6_width: 1920
63+
z6_height: 1080
5864
z6_x: 0
5965
z6_y: 0
6066
z7_active: false
6167
z7_path: ""
6268
z7_volume: 100
6369
z7_width: 1920
70+
z7_height: 1080
6471
z7_x: 0
6572
z7_y: 0
73+
z8_active: false
74+
z8_path: ""
75+
z8_volume: 100
76+
z8_width: 1920
77+
z8_height: 1080
78+
z8_x: 0
79+
z8_y: 0
6680

6781
ffmpeg_source:
6882
active: false

internal/config/config.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,40 +65,45 @@ func chromiumSourceDiff(old, new models.ChromiumSource) bool {
6565
}
6666
if old.Z1Active != new.Z1Active || old.Z1Path != new.Z1Path ||
6767
old.Z1BgColor != new.Z1BgColor ||
68-
!ptrIntEqual(old.Z1Volume, new.Z1Volume) || !ptrIntEqual(old.Z1Width, new.Z1Width) ||
68+
!ptrIntEqual(old.Z1Volume, new.Z1Volume) || !ptrIntEqual(old.Z1Width, new.Z1Width) || !ptrIntEqual(old.Z1Height, new.Z1Height) ||
6969
!ptrIntEqual(old.Z1X, new.Z1X) || !ptrIntEqual(old.Z1Y, new.Z1Y) {
7070
return true
7171
}
7272
if old.Z2Active != new.Z2Active || old.Z2Path != new.Z2Path ||
73-
!ptrIntEqual(old.Z2Volume, new.Z2Volume) || !ptrIntEqual(old.Z2Width, new.Z2Width) ||
73+
!ptrIntEqual(old.Z2Volume, new.Z2Volume) || !ptrIntEqual(old.Z2Width, new.Z2Width) || !ptrIntEqual(old.Z2Height, new.Z2Height) ||
7474
!ptrIntEqual(old.Z2X, new.Z2X) || !ptrIntEqual(old.Z2Y, new.Z2Y) {
7575
return true
7676
}
7777
if old.Z3Active != new.Z3Active || old.Z3Path != new.Z3Path ||
78-
!ptrIntEqual(old.Z3Volume, new.Z3Volume) || !ptrIntEqual(old.Z3Width, new.Z3Width) ||
78+
!ptrIntEqual(old.Z3Volume, new.Z3Volume) || !ptrIntEqual(old.Z3Width, new.Z3Width) || !ptrIntEqual(old.Z3Height, new.Z3Height) ||
7979
!ptrIntEqual(old.Z3X, new.Z3X) || !ptrIntEqual(old.Z3Y, new.Z3Y) {
8080
return true
8181
}
8282
if old.Z4Active != new.Z4Active || old.Z4Path != new.Z4Path ||
83-
!ptrIntEqual(old.Z4Volume, new.Z4Volume) || !ptrIntEqual(old.Z4Width, new.Z4Width) ||
83+
!ptrIntEqual(old.Z4Volume, new.Z4Volume) || !ptrIntEqual(old.Z4Width, new.Z4Width) || !ptrIntEqual(old.Z4Height, new.Z4Height) ||
8484
!ptrIntEqual(old.Z4X, new.Z4X) || !ptrIntEqual(old.Z4Y, new.Z4Y) {
8585
return true
8686
}
8787
if old.Z5Active != new.Z5Active || old.Z5Path != new.Z5Path ||
88-
!ptrIntEqual(old.Z5Volume, new.Z5Volume) || !ptrIntEqual(old.Z5Width, new.Z5Width) ||
88+
!ptrIntEqual(old.Z5Volume, new.Z5Volume) || !ptrIntEqual(old.Z5Width, new.Z5Width) || !ptrIntEqual(old.Z5Height, new.Z5Height) ||
8989
!ptrIntEqual(old.Z5X, new.Z5X) || !ptrIntEqual(old.Z5Y, new.Z5Y) {
9090
return true
9191
}
9292
if old.Z6Active != new.Z6Active || old.Z6Path != new.Z6Path ||
93-
!ptrIntEqual(old.Z6Volume, new.Z6Volume) || !ptrIntEqual(old.Z6Width, new.Z6Width) ||
93+
!ptrIntEqual(old.Z6Volume, new.Z6Volume) || !ptrIntEqual(old.Z6Width, new.Z6Width) || !ptrIntEqual(old.Z6Height, new.Z6Height) ||
9494
!ptrIntEqual(old.Z6X, new.Z6X) || !ptrIntEqual(old.Z6Y, new.Z6Y) {
9595
return true
9696
}
9797
if old.Z7Active != new.Z7Active || old.Z7Path != new.Z7Path ||
98-
!ptrIntEqual(old.Z7Volume, new.Z7Volume) || !ptrIntEqual(old.Z7Width, new.Z7Width) ||
98+
!ptrIntEqual(old.Z7Volume, new.Z7Volume) || !ptrIntEqual(old.Z7Width, new.Z7Width) || !ptrIntEqual(old.Z7Height, new.Z7Height) ||
9999
!ptrIntEqual(old.Z7X, new.Z7X) || !ptrIntEqual(old.Z7Y, new.Z7Y) {
100100
return true
101101
}
102+
if old.Z8Active != new.Z8Active || old.Z8Path != new.Z8Path ||
103+
!ptrIntEqual(old.Z8Volume, new.Z8Volume) || !ptrIntEqual(old.Z8Width, new.Z8Width) || !ptrIntEqual(old.Z8Height, new.Z8Height) ||
104+
!ptrIntEqual(old.Z8X, new.Z8X) || !ptrIntEqual(old.Z8Y, new.Z8Y) {
105+
return true
106+
}
102107
return false
103108
}
104109

internal/engine/manager.go

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (pm *ProcessManager) Stop() {
129129
pm.mu.Unlock()
130130
}
131131

132-
func buildOverlayElement(id string, zIndex int, path string, width, x, y, volume *int) (string, string, string) {
132+
func buildOverlayElement(id string, zIndex int, path string, width, height, x, y, volume *int) (string, string, string) {
133133
if path == "" {
134134
return "", "", ""
135135
}
@@ -148,6 +148,9 @@ func buildOverlayElement(id string, zIndex int, path string, width, x, y, volume
148148
if width != nil {
149149
style += fmt.Sprintf("width: %dpx; ", *width)
150150
}
151+
if height != nil {
152+
style += fmt.Sprintf("height: %dpx; ", *height)
153+
}
151154
style += "}\n"
152155

153156
var element string
@@ -199,11 +202,19 @@ func (pm *ProcessManager) manageOverlays(cfg *models.Config) {
199202

200203
if shouldStart {
201204
cs := cfg.Input.ChromiumSource
202-
bgColor := "transparent"
205+
bgColor := "#00FF00"
203206
if cs.Z1BgColor != "" {
204207
bgColor = cs.Z1BgColor
205208
}
206209

210+
resParts := strings.Split(cfg.Input.Resolution, "x")
211+
resWidth := "1920"
212+
resHeight := "1080"
213+
if len(resParts) == 2 {
214+
resWidth = resParts[0]
215+
resHeight = resParts[1]
216+
}
217+
207218
// Generate HTML file
208219
htmlContent := `<!DOCTYPE html>
209220
<html>
@@ -217,51 +228,57 @@ func (pm *ProcessManager) manageOverlays(cfg *models.Config) {
217228
var scripts string
218229

219230
if cs.Z1Active {
220-
s, e, sc := buildOverlayElement("z1", 1, cs.Z1Path, cs.Z1Width, cs.Z1X, cs.Z1Y, cs.Z1Volume)
231+
s, e, sc := buildOverlayElement("z1", 1, cs.Z1Path, cs.Z1Width, cs.Z1Height, cs.Z1X, cs.Z1Y, cs.Z1Volume)
221232
htmlContent += s
222233
elements += e
223234
scripts += sc
224235
}
225236
if cs.Z2Active {
226-
s, e, sc := buildOverlayElement("z2", 2, cs.Z2Path, cs.Z2Width, cs.Z2X, cs.Z2Y, cs.Z2Volume)
237+
s, e, sc := buildOverlayElement("z2", 2, cs.Z2Path, cs.Z2Width, cs.Z2Height, cs.Z2X, cs.Z2Y, cs.Z2Volume)
227238
htmlContent += s
228239
elements += e
229240
scripts += sc
230241
}
231242
if cs.Z3Active {
232-
s, e, sc := buildOverlayElement("z3", 3, cs.Z3Path, cs.Z3Width, cs.Z3X, cs.Z3Y, cs.Z3Volume)
243+
s, e, sc := buildOverlayElement("z3", 3, cs.Z3Path, cs.Z3Width, cs.Z3Height, cs.Z3X, cs.Z3Y, cs.Z3Volume)
233244
htmlContent += s
234245
elements += e
235246
scripts += sc
236247
}
237248
if cs.Z4Active {
238-
s, e, sc := buildOverlayElement("z4", 4, cs.Z4Path, cs.Z4Width, cs.Z4X, cs.Z4Y, cs.Z4Volume)
249+
s, e, sc := buildOverlayElement("z4", 4, cs.Z4Path, cs.Z4Width, cs.Z4Height, cs.Z4X, cs.Z4Y, cs.Z4Volume)
239250
htmlContent += s
240251
elements += e
241252
scripts += sc
242253
}
243254
if cs.Z5Active {
244-
s, e, sc := buildOverlayElement("z5", 5, cs.Z5Path, cs.Z5Width, cs.Z5X, cs.Z5Y, cs.Z5Volume)
255+
s, e, sc := buildOverlayElement("z5", 5, cs.Z5Path, cs.Z5Width, cs.Z5Height, cs.Z5X, cs.Z5Y, cs.Z5Volume)
245256
htmlContent += s
246257
elements += e
247258
scripts += sc
248259
}
249260
if cs.Z6Active {
250-
s, e, sc := buildOverlayElement("z6", 6, cs.Z6Path, cs.Z6Width, cs.Z6X, cs.Z6Y, cs.Z6Volume)
261+
s, e, sc := buildOverlayElement("z6", 6, cs.Z6Path, cs.Z6Width, cs.Z6Height, cs.Z6X, cs.Z6Y, cs.Z6Volume)
251262
htmlContent += s
252263
elements += e
253264
scripts += sc
254265
}
255266
if cs.Z7Active {
256-
s, e, sc := buildOverlayElement("z7", 7, cs.Z7Path, cs.Z7Width, cs.Z7X, cs.Z7Y, cs.Z7Volume)
267+
s, e, sc := buildOverlayElement("z7", 7, cs.Z7Path, cs.Z7Width, cs.Z7Height, cs.Z7X, cs.Z7Y, cs.Z7Volume)
268+
htmlContent += s
269+
elements += e
270+
scripts += sc
271+
}
272+
if cs.Z8Active {
273+
s, e, sc := buildOverlayElement("z8", 8, cs.Z8Path, cs.Z8Width, cs.Z8Height, cs.Z8X, cs.Z8Y, cs.Z8Volume)
257274
htmlContent += s
258275
elements += e
259276
scripts += sc
260277
}
261278

262279
htmlContent += `</style>
263280
</head>
264-
<body style="margin: 0; padding: 0;">
281+
<body style="margin: 0; padding: 0; width: ` + resWidth + `px; height: ` + resHeight + `px;">
265282
`
266283
htmlContent += elements
267284
if scripts != "" {
@@ -295,18 +312,10 @@ func (pm *ProcessManager) manageOverlays(cfg *models.Config) {
295312
}
296313
}
297314

298-
resParts := strings.Split(cfg.Input.Resolution, "x")
299-
width := "1920"
300-
height := "1080"
301-
if len(resParts) == 2 {
302-
width = resParts[0]
303-
height = resParts[1]
304-
}
305-
306-
cmd := exec.Command("xvfb-run", serverNum, fmt.Sprintf("--server-args=-screen 0 %sx%sx24 -ac", width, height),
315+
cmd := exec.Command("xvfb-run", serverNum, fmt.Sprintf("--server-args=-screen 0 %sx%sx24 -ac", resWidth, resHeight),
307316
chromeBin, "--kiosk", "--disable-infobars", "--disable-extensions", "--test-type",
308-
fmt.Sprintf("--window-size=%s,%s", width, height), "--window-position=0,0", "--hide-scrollbars","--no-sandbox", "--disable-dev-shm-usage",
309-
"--autoplay-policy=no-user-gesture-required", fileURL)
317+
fmt.Sprintf("--window-size=%s,%s", resWidth, resHeight), "--window-position=0,0", "--hide-scrollbars","--no-sandbox", "--disable-dev-shm-usage",
318+
"--autoplay-policy=no-user-gesture-required", "--force-device-scale-factor=1", fileURL)
310319

311320
err = cmd.Start()
312321
if err != nil {

internal/engine/mixer/mixer.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,27 @@ func BuildFilterComplex(cfg *models.Config) ([]string, string, string, string) {
101101
if cfg.Input.ChromiumSource.Active {
102102
args = append(args, "-f", "x11grab", "-video_size", cfg.Input.Resolution, "-draw_mouse", "0", "-i", ":99")
103103

104+
chromaColor := cfg.Input.ChromiumSource.Z1BgColor
105+
if chromaColor == "" {
106+
chromaColor = "#00FF00"
107+
}
108+
if strings.HasPrefix(chromaColor, "#") {
109+
chromaColor = "0x" + chromaColor[1:]
110+
}
111+
104112
layerVideoPad := string(append(strconv.AppendInt([]byte("["), int64(inputIdx), 10), ":v]"...))
113+
chromaPad := "[chroma_chromium]"
105114
outPad := "[out_chromium]"
106115

107-
filterComplex.WriteString(currentBasePad)
108116
filterComplex.WriteString(layerVideoPad)
117+
filterComplex.WriteString(" colorkey=")
118+
filterComplex.WriteString(chromaColor)
119+
filterComplex.WriteString(":0.1:0.1 ")
120+
filterComplex.WriteString(chromaPad)
121+
filterComplex.WriteString(";\n")
122+
123+
filterComplex.WriteString(currentBasePad)
124+
filterComplex.WriteString(chromaPad)
109125
filterComplex.WriteString(" overlay=x=0:y=0 ")
110126
filterComplex.WriteString(outPad)
111127
filterComplex.WriteString(";\n")

internal/engine/source/source.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func BuildInputArgs(layer models.Layer) models.InputResult {
164164
if layer.FolderOptions.Loop {
165165
args = append(args, "-stream_loop", "-1")
166166
}
167-
args = append(args, "-f", "concat", "-safe", "0", "-i", playlistPath)
167+
args = append(args, "-fflags", "+genpts+igndts", "-f", "concat", "-safe", "0", "-async", "1", "-vsync", "1", "-i", playlistPath)
168168
return models.InputResult{Args: args, InputCount: 1, HasVideo: true, HasAudio: true}
169169
} else {
170170
args = append(args, "-re", "-stream_loop", "-1", "-i", videos[0])

internal/models/models.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,65 @@ type ChromiumSource struct {
2121
Z1BgColor string `yaml:"bg-color"`
2222
Z1Volume *int `yaml:"z1_volume"`
2323
Z1Width *int `yaml:"z1_width"`
24+
Z1Height *int `yaml:"z1_height"`
2425
Z1X *int `yaml:"z1_x"`
2526
Z1Y *int `yaml:"z1_y"`
2627

2728
Z2Active bool `yaml:"z2_active"`
2829
Z2Path string `yaml:"z2_path"`
2930
Z2Volume *int `yaml:"z2_volume"`
3031
Z2Width *int `yaml:"z2_width"`
32+
Z2Height *int `yaml:"z2_height"`
3133
Z2X *int `yaml:"z2_x"`
3234
Z2Y *int `yaml:"z2_y"`
3335

3436
Z3Active bool `yaml:"z3_active"`
3537
Z3Path string `yaml:"z3_path"`
3638
Z3Volume *int `yaml:"z3_volume"`
3739
Z3Width *int `yaml:"z3_width"`
40+
Z3Height *int `yaml:"z3_height"`
3841
Z3X *int `yaml:"z3_x"`
3942
Z3Y *int `yaml:"z3_y"`
4043

4144
Z4Active bool `yaml:"z4_active"`
4245
Z4Path string `yaml:"z4_path"`
4346
Z4Volume *int `yaml:"z4_volume"`
4447
Z4Width *int `yaml:"z4_width"`
48+
Z4Height *int `yaml:"z4_height"`
4549
Z4X *int `yaml:"z4_x"`
4650
Z4Y *int `yaml:"z4_y"`
4751

4852
Z5Active bool `yaml:"z5_active"`
4953
Z5Path string `yaml:"z5_path"`
5054
Z5Volume *int `yaml:"z5_volume"`
5155
Z5Width *int `yaml:"z5_width"`
56+
Z5Height *int `yaml:"z5_height"`
5257
Z5X *int `yaml:"z5_x"`
5358
Z5Y *int `yaml:"z5_y"`
5459

5560
Z6Active bool `yaml:"z6_active"`
5661
Z6Path string `yaml:"z6_path"`
5762
Z6Volume *int `yaml:"z6_volume"`
5863
Z6Width *int `yaml:"z6_width"`
64+
Z6Height *int `yaml:"z6_height"`
5965
Z6X *int `yaml:"z6_x"`
6066
Z6Y *int `yaml:"z6_y"`
6167

6268
Z7Active bool `yaml:"z7_active"`
6369
Z7Path string `yaml:"z7_path"`
6470
Z7Volume *int `yaml:"z7_volume"`
6571
Z7Width *int `yaml:"z7_width"`
72+
Z7Height *int `yaml:"z7_height"`
6673
Z7X *int `yaml:"z7_x"`
6774
Z7Y *int `yaml:"z7_y"`
75+
76+
Z8Active bool `yaml:"z8_active"`
77+
Z8Path string `yaml:"z8_path"`
78+
Z8Volume *int `yaml:"z8_volume"`
79+
Z8Width *int `yaml:"z8_width"`
80+
Z8Height *int `yaml:"z8_height"`
81+
Z8X *int `yaml:"z8_x"`
82+
Z8Y *int `yaml:"z8_y"`
6883
}
6984

7085
type InputSettings struct {

0 commit comments

Comments
 (0)