Publish Muninn OBS stream catalog
This commit is contained in:
parent
2d88408007
commit
66a3df8ad2
5 changed files with 86 additions and 6 deletions
|
|
@ -37,6 +37,7 @@ struct Options {
|
|||
ffmpeg_path: String,
|
||||
loopback_script: PathBuf,
|
||||
log_root: PathBuf,
|
||||
obs_catalog_path: PathBuf,
|
||||
interval_seconds: Option<u64>,
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +163,7 @@ fn publish_surface(
|
|||
state: &str,
|
||||
active_streams: &[String],
|
||||
) -> Result<()> {
|
||||
write_obs_catalog_idle(options)?;
|
||||
let record = MuninnTelemetrySurfaceRecord {
|
||||
surface_id: options.surface_id.clone(),
|
||||
host_id: options.host_id.clone(),
|
||||
|
|
@ -209,6 +211,7 @@ fn publish_stream(
|
|||
restart_count: u32,
|
||||
detail: &str,
|
||||
) -> Result<()> {
|
||||
write_obs_catalog_active(options, plan, state)?;
|
||||
let record = MuninnCaptureStreamRecord {
|
||||
stream_id: options.stream_id.clone(),
|
||||
host_id: options.host_id.clone(),
|
||||
|
|
@ -235,6 +238,47 @@ fn publish_stream(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_obs_catalog_idle(options: &Options) -> Result<()> {
|
||||
if let Some(parent) = options.obs_catalog_path.parent() {
|
||||
fs::create_dir_all(parent).with_context(|| format!("creating {}", parent.display()))?;
|
||||
}
|
||||
let mut lines = vec![
|
||||
"# stream_id\tlabel\turl\tstate".to_string(),
|
||||
format!(
|
||||
"{}\t{} screen and loopback A/V\t\tactivation-required",
|
||||
options.stream_id, options.host_id
|
||||
),
|
||||
];
|
||||
for source in available_sources(options) {
|
||||
lines.push(format!(
|
||||
"{}:{}\t{}\t\taffordance",
|
||||
options.surface_id, source, source
|
||||
));
|
||||
}
|
||||
fs::write(&options.obs_catalog_path, lines.join("\r\n") + "\r\n")
|
||||
.with_context(|| format!("writing {}", options.obs_catalog_path.display()))
|
||||
}
|
||||
|
||||
fn write_obs_catalog_active(options: &Options, plan: &MuxPlan, state: &str) -> Result<()> {
|
||||
if let Some(parent) = options.obs_catalog_path.parent() {
|
||||
fs::create_dir_all(parent).with_context(|| format!("creating {}", parent.display()))?;
|
||||
}
|
||||
let mut lines = vec!["# stream_id\tlabel\turl\tstate".to_string()];
|
||||
for (index, target) in plan.targets.iter().enumerate() {
|
||||
lines.push(format!(
|
||||
"{}:{}\t{} A/V target {}\t{}\t{}",
|
||||
options.stream_id,
|
||||
index,
|
||||
options.host_id,
|
||||
index + 1,
|
||||
target,
|
||||
state
|
||||
));
|
||||
}
|
||||
fs::write(&options.obs_catalog_path, lines.join("\r\n") + "\r\n")
|
||||
.with_context(|| format!("writing {}", options.obs_catalog_path.display()))
|
||||
}
|
||||
|
||||
fn health_check(options: &Options) -> Result<()> {
|
||||
let node = open_node(options, "muninn-health")?;
|
||||
let surface = node
|
||||
|
|
@ -421,6 +465,7 @@ impl Options {
|
|||
ffmpeg_path: "ffmpeg".to_string(),
|
||||
loopback_script: PathBuf::from("scripts/wasapi-loopback-capture.ps1"),
|
||||
log_root: PathBuf::from("C:/Meta/Odin/logs/muninn"),
|
||||
obs_catalog_path: PathBuf::from("C:/Meta/Odin/state/muninn-obs-streams.tsv"),
|
||||
interval_seconds: None,
|
||||
};
|
||||
|
||||
|
|
@ -467,6 +512,10 @@ impl Options {
|
|||
"--log-root" => {
|
||||
options.log_root = PathBuf::from(take_value(&mut args, "--log-root")?)
|
||||
}
|
||||
"--obs-catalog" => {
|
||||
options.obs_catalog_path =
|
||||
PathBuf::from(take_value(&mut args, "--obs-catalog")?)
|
||||
}
|
||||
"--interval-seconds" => {
|
||||
options.interval_seconds = Some(
|
||||
take_value(&mut args, "--interval-seconds")?
|
||||
|
|
|
|||
|
|
@ -29,6 +29,17 @@ muninn --health --store C:\Meta\Odin\state\muninn.telemetry.cc
|
|||
surface fresh without starting FFmpeg, screen capture, microphone capture, or
|
||||
loopback capture.
|
||||
|
||||
Muninn also writes an OBS compatibility catalog by default:
|
||||
|
||||
```text
|
||||
C:\Meta\Odin\state\muninn-obs-streams.tsv
|
||||
```
|
||||
|
||||
That TSV is a lowering of Muninn's typed state for OBS source property lists. It
|
||||
is not the authority; the `.cc` CultMesh store is. On Starfire,
|
||||
`health-muninn.ps1` syncs Raven's catalog to the same local path so the OBS
|
||||
plugin can read it without learning Raven SSH or CultCache internals.
|
||||
|
||||
Activation is explicit:
|
||||
|
||||
```powershell
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ param(
|
|||
[string] $RavenHost = "raven",
|
||||
[string] $MuninnExe = "C:\Meta\Odin\Muninn\muninn.exe",
|
||||
[string] $StorePath = "C:\Meta\Odin\state\muninn.telemetry.cc",
|
||||
[string] $ObsCatalogPath = "C:\Meta\Odin\state\muninn-obs-streams.tsv",
|
||||
[string] $LoopbackScript = "C:\Meta\Odin\Muninn\scripts\wasapi-loopback-capture.ps1",
|
||||
[string] $LogRoot = "C:\Meta\Odin\logs\muninn",
|
||||
[string] $Ffmpeg = "C:\Users\Madman's Lullaby\AppData\Local\Microsoft\WinGet\Links\ffmpeg.exe",
|
||||
|
|
@ -32,7 +33,7 @@ Get-CimInstance Win32_Process |
|
|||
`$lines = @(
|
||||
"@echo off",
|
||||
"cd /d ""`$muninnDir""",
|
||||
"""$MuninnExe"" activate --store ""$StorePath"" --host raven --stream muninn.raven.av.srt --target-host ""$TargetHost"" --port $Port --obs-target-host ""$ObsTargetHost"" --obs-port $ObsPort --audio-device ""$AudioDevice"" --ffmpeg ""$Ffmpeg"" --loopback-script ""$LoopbackScript"" --log-root ""$LogRoot"" 1>>""$LogRoot\muninn-activate.out.log"" 2>>""$LogRoot\muninn-activate.err.log"""
|
||||
"""$MuninnExe"" activate --store ""$StorePath"" --obs-catalog ""$ObsCatalogPath"" --host raven --stream muninn.raven.av.srt --target-host ""$TargetHost"" --port $Port --obs-target-host ""$ObsTargetHost"" --obs-port $ObsPort --audio-device ""$AudioDevice"" --ffmpeg ""$Ffmpeg"" --loopback-script ""$LoopbackScript"" --log-root ""$LogRoot"" 1>>""$LogRoot\muninn-activate.out.log"" 2>>""$LogRoot\muninn-activate.err.log"""
|
||||
)
|
||||
Set-Content -LiteralPath `$launcher -Value `$lines -Encoding ASCII
|
||||
cmd /c "schtasks /Delete /TN GameCult-Muninn-Activate /F 2>NUL"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
param(
|
||||
[string] $RavenHost = "raven",
|
||||
[string] $MuninnExe = "C:\Meta\Odin\Muninn\muninn.exe",
|
||||
[string] $StorePath = "C:\Meta\Odin\state\muninn.telemetry.cc"
|
||||
[string] $StorePath = "C:\Meta\Odin\state\muninn.telemetry.cc",
|
||||
[string] $RemoteObsCatalogPath = "C:\Meta\Odin\state\muninn-obs-streams.tsv",
|
||||
[string] $LocalObsCatalogPath = "C:\Meta\Odin\state\muninn-obs-streams.tsv"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
@ -22,4 +24,13 @@ if (`$null -eq `$process) {
|
|||
|
||||
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($remoteScript))
|
||||
& ssh.exe -o BatchMode=yes -o ConnectTimeout=5 $RavenHost "powershell.exe -NoProfile -EncodedCommand $encoded"
|
||||
exit $LASTEXITCODE
|
||||
$healthExit = $LASTEXITCODE
|
||||
if ($healthExit -eq 0) {
|
||||
$localParent = Split-Path -Parent $LocalObsCatalogPath
|
||||
if (-not [string]::IsNullOrWhiteSpace($localParent)) {
|
||||
New-Item -ItemType Directory -Force -Path $localParent | Out-Null
|
||||
}
|
||||
& ssh.exe -o BatchMode=yes -o ConnectTimeout=5 $RavenHost "cmd /c type $RemoteObsCatalogPath" |
|
||||
Set-Content -Encoding UTF8 -LiteralPath $LocalObsCatalogPath
|
||||
}
|
||||
exit $healthExit
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ param(
|
|||
[string] $RavenHost = "raven",
|
||||
[string] $MuninnExe = "C:\Meta\Odin\Muninn\muninn.exe",
|
||||
[string] $StorePath = "C:\Meta\Odin\state\muninn.telemetry.cc",
|
||||
[string] $LogRoot = "C:\Meta\Odin\logs\muninn"
|
||||
[string] $ObsCatalogPath = "C:\Meta\Odin\state\muninn-obs-streams.tsv",
|
||||
[string] $LogRoot = "C:\Meta\Odin\logs\muninn",
|
||||
[string] $LocalObsCatalogPath = "C:\Meta\Odin\state\muninn-obs-streams.tsv"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
@ -24,7 +26,7 @@ New-Item -ItemType Directory -Force -Path (Split-Path -Parent "$StorePath") | Ou
|
|||
`$lines = @(
|
||||
"@echo off",
|
||||
"cd /d ""`$muninnDir""",
|
||||
"""$MuninnExe"" serve --store ""$StorePath"" --log-root ""$LogRoot"" --host raven --interval-seconds 15 1>>""$LogRoot\muninn-serve.out.log"" 2>>""$LogRoot\muninn-serve.err.log"""
|
||||
"""$MuninnExe"" serve --store ""$StorePath"" --obs-catalog ""$ObsCatalogPath"" --log-root ""$LogRoot"" --host raven --interval-seconds 15 1>>""$LogRoot\muninn-serve.out.log"" 2>>""$LogRoot\muninn-serve.err.log"""
|
||||
)
|
||||
Set-Content -LiteralPath `$launcher -Value `$lines -Encoding ASCII
|
||||
cmd /c "schtasks /Delete /TN GameCult-Muninn /F 2>NUL"
|
||||
|
|
@ -34,4 +36,10 @@ cmd /c schtasks /Run /TN GameCult-Muninn
|
|||
|
||||
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($remoteScript))
|
||||
& ssh.exe -o BatchMode=yes -o ConnectTimeout=10 $RavenHost "powershell.exe -NoProfile -EncodedCommand $encoded"
|
||||
exit $LASTEXITCODE
|
||||
$restartExit = $LASTEXITCODE
|
||||
if ($restartExit -eq 0) {
|
||||
Start-Sleep -Seconds 2
|
||||
$healthScript = Join-Path $PSScriptRoot "health-muninn.ps1"
|
||||
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $healthScript -RavenHost $RavenHost -MuninnExe $MuninnExe -StorePath $StorePath -RemoteObsCatalogPath $ObsCatalogPath -LocalObsCatalogPath $LocalObsCatalogPath
|
||||
}
|
||||
exit $restartExit
|
||||
|
|
|
|||
Loading…
Reference in a new issue