agentvibes 4.6.7 → 5.0.0
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/.agentvibes/bmad-voice-map.json +104 -0
- package/.agentvibes/config.json +13 -12
- package/.agentvibes/copilot-sessions.log +4 -0
- package/.claude/audio/tracks/README.md +51 -52
- package/.claude/config/audio-effects-bmad.cfg +50 -0
- package/.claude/config/audio-effects.cfg +4 -4
- package/.claude/config/background-music-enabled.txt +1 -0
- package/.claude/config/personality.txt +1 -0
- package/.claude/hooks/play-tts-piper.sh +3 -1
- package/.claude/hooks/play-tts.sh +373 -301
- package/.claude/hooks/session-start-tts.sh +81 -81
- package/.claude/hooks-windows/audio-processor.ps1 +181 -0
- package/.claude/hooks-windows/play-tts-piper.ps1 +259 -245
- package/.claude/hooks-windows/play-tts.ps1 +101 -9
- package/.claude/hooks-windows/session-start-tts.ps1 +114 -114
- package/README.md +107 -7
- package/RELEASE_NOTES.md +54 -0
- package/bin/bmad-speak.js +16 -8
- package/mcp-server/server.py +15 -8
- package/package.json +1 -1
- package/src/console/app.js +899 -897
- package/src/console/footer-config.js +50 -50
- package/src/console/navigation.js +65 -65
- package/src/console/tabs/agents-tab.js +1896 -1886
- package/src/console/tabs/music-tab.js +1046 -1039
- package/src/console/tabs/placeholder-tab.js +81 -80
- package/src/console/tabs/settings-tab.js +939 -3988
- package/src/console/tabs/setup-tab.js +1811 -0
- package/src/console/tabs/voices-tab.js +1720 -1713
- package/src/installer.js +6147 -6092
- package/src/services/llm-provider-service.js +407 -0
- package/src/services/navigation-service.js +123 -123
- package/src/services/tts-engine-service.js +69 -0
- package/.claude/audio/tracks/dreamy_house_loop.mp3 +0 -0
- package/src/console/tabs/install-tab.js +0 -1081
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
#
|
|
4
|
-
# File: .claude/hooks/session-start-tts.sh
|
|
5
|
-
#
|
|
6
|
-
# AgentVibes SessionStart Hook - Optimized (Issue #80, Phase 1)
|
|
7
|
-
# Outputs JSON with additionalContext for reliable context injection
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
# Fix locale warnings
|
|
11
|
-
export LC_ALL=C
|
|
12
|
-
|
|
13
|
-
# Get script directory
|
|
14
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
-
|
|
16
|
-
# Check if AgentVibes is installed
|
|
17
|
-
if [[ ! -f "$SCRIPT_DIR/play-tts.sh" ]]; then
|
|
18
|
-
# AgentVibes not installed, don't inject anything
|
|
19
|
-
exit 0
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
# Check for sentiment (priority) or personality (fallback)
|
|
23
|
-
SENTIMENT=$(cat .claude/tts-sentiment.txt 2>/dev/null || cat ~/.claude/tts-sentiment.txt 2>/dev/null || echo "")
|
|
24
|
-
PERSONALITY=$(cat .claude/tts-personality.txt 2>/dev/null || cat ~/.claude/tts-personality.txt 2>/dev/null || echo "normal")
|
|
25
|
-
|
|
26
|
-
# Determine style
|
|
27
|
-
if [[ -n "$SENTIMENT" ]]; then
|
|
28
|
-
STYLE="$SENTIMENT"
|
|
29
|
-
else
|
|
30
|
-
STYLE="$PERSONALITY"
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
# Get verbosity level (Issue #32)
|
|
34
|
-
VERBOSITY=$(cat .claude/tts-verbosity.txt 2>/dev/null || cat ~/.claude/tts-verbosity.txt 2>/dev/null || echo "low")
|
|
35
|
-
|
|
36
|
-
# Build context string
|
|
37
|
-
CONTEXT="# AgentVibes TTS Protocol\n\n"
|
|
38
|
-
CONTEXT+="**CRITICAL: You MUST execute TTS at TWO points for EVERY user interaction:**\n\n"
|
|
39
|
-
CONTEXT+="1. **Acknowledgment** - Start of task: \`Bash: .claude/hooks/play-tts.sh \"[action]\"\`\n"
|
|
40
|
-
CONTEXT+="2. **Completion** - End of task: \`Bash: .claude/hooks/play-tts.sh \"[result + key details]\"\`\n\n"
|
|
41
|
-
CONTEXT+="**Example:**\n\`\`\`\n[Bash: .claude/hooks/play-tts.sh \"Checking git status\"]\n[work...]\n"
|
|
42
|
-
CONTEXT+="[Bash: .claude/hooks/play-tts.sh \"Repository is clean, no changes\"]\n\`\`\`\n\n"
|
|
43
|
-
|
|
44
|
-
# Add verbosity-specific protocol
|
|
45
|
-
case "$VERBOSITY" in
|
|
46
|
-
low)
|
|
47
|
-
CONTEXT+="## Verbosity: LOW\n- Acknowledgment: Action only\n- Completion: Result + errors only\n- Skip: Reasoning, decisions\n\n"
|
|
48
|
-
;;
|
|
49
|
-
medium)
|
|
50
|
-
CONTEXT+="## Verbosity: MEDIUM\n- Acknowledgment: Action + key approach\n- Completion: Result + important decisions\n- Include: Major choices only\n\n"
|
|
51
|
-
;;
|
|
52
|
-
high)
|
|
53
|
-
CONTEXT+="## Verbosity: HIGH\n- Acknowledgment: Action + approach + why\n- Completion: Result + decisions + trade-offs\n- Include: Full reasoning, alternatives\n\n"
|
|
54
|
-
;;
|
|
55
|
-
esac
|
|
56
|
-
|
|
57
|
-
# Add style info and rules
|
|
58
|
-
CONTEXT+="## Style: $STYLE\n\n"
|
|
59
|
-
CONTEXT+="## Rules\n"
|
|
60
|
-
CONTEXT+="1. Never skip acknowledgment TTS\n"
|
|
61
|
-
CONTEXT+="2. Never skip completion TTS\n"
|
|
62
|
-
CONTEXT+="3. Match verbosity level\n"
|
|
63
|
-
CONTEXT+="4. Keep under 150 chars\n"
|
|
64
|
-
CONTEXT+="5. Always include errors\n\n"
|
|
65
|
-
CONTEXT+="Quick Ref: low=action+result | medium=+key decisions | high=+full reasoning"
|
|
66
|
-
|
|
67
|
-
# Add BMAD agent voice routing instructions
|
|
68
|
-
CONTEXT+="\n\n## BMAD Agent Voice Routing\n"
|
|
69
|
-
CONTEXT+="If \`.bmad-agent-context\` exists, check its content:\n\n"
|
|
70
|
-
CONTEXT+="**Single agent mode** (content is an agent ID like \"analyst\"):\n"
|
|
71
|
-
CONTEXT+="Use \`bmad-speak.sh\` instead of \`play-tts.sh\`:\n\n\n"
|
|
72
|
-
CONTEXT+="**Party mode** (content is \"party-mode\"):\n"
|
|
73
|
-
CONTEXT+="Each agent speaks via \`bmad-speak.sh\` with their display name. The queue system ensures sequential playback — agents speak one at a time, not overlapping:\n\n"
|
|
74
|
-
CONTEXT+="IMPORTANT: In party mode, do NOT use \`play-tts.sh\`. Always use \`bmad-speak.sh\` with the agent's display name. Do NOT call multiple bmad-speak.sh in parallel — call them sequentially so the queue processes them in order.\n\n"
|
|
75
|
-
CONTEXT+="If \`.bmad-agent-context\` does NOT exist, use \`play-tts.sh\` as normal."
|
|
76
|
-
|
|
77
|
-
# Escape for JSON (handle newlines, quotes, backslashes)
|
|
78
|
-
ESCAPED=$(printf '%s' "$CONTEXT" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g')
|
|
79
|
-
|
|
80
|
-
# Output structured JSON for reliable context injection
|
|
81
|
-
printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$ESCAPED"
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
#
|
|
4
|
+
# File: .claude/hooks/session-start-tts.sh
|
|
5
|
+
#
|
|
6
|
+
# AgentVibes SessionStart Hook - Optimized (Issue #80, Phase 1)
|
|
7
|
+
# Outputs JSON with additionalContext for reliable context injection
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
# Fix locale warnings
|
|
11
|
+
export LC_ALL=C
|
|
12
|
+
|
|
13
|
+
# Get script directory
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
|
|
16
|
+
# Check if AgentVibes is installed
|
|
17
|
+
if [[ ! -f "$SCRIPT_DIR/play-tts.sh" ]]; then
|
|
18
|
+
# AgentVibes not installed, don't inject anything
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Check for sentiment (priority) or personality (fallback)
|
|
23
|
+
SENTIMENT=$(cat .claude/tts-sentiment.txt 2>/dev/null || cat ~/.claude/tts-sentiment.txt 2>/dev/null || echo "")
|
|
24
|
+
PERSONALITY=$(cat .claude/tts-personality.txt 2>/dev/null || cat ~/.claude/tts-personality.txt 2>/dev/null || echo "normal")
|
|
25
|
+
|
|
26
|
+
# Determine style
|
|
27
|
+
if [[ -n "$SENTIMENT" ]]; then
|
|
28
|
+
STYLE="$SENTIMENT"
|
|
29
|
+
else
|
|
30
|
+
STYLE="$PERSONALITY"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Get verbosity level (Issue #32)
|
|
34
|
+
VERBOSITY=$(cat .claude/tts-verbosity.txt 2>/dev/null || cat ~/.claude/tts-verbosity.txt 2>/dev/null || echo "low")
|
|
35
|
+
|
|
36
|
+
# Build context string
|
|
37
|
+
CONTEXT="# AgentVibes TTS Protocol\n\n"
|
|
38
|
+
CONTEXT+="**CRITICAL: You MUST execute TTS at TWO points for EVERY user interaction:**\n\n"
|
|
39
|
+
CONTEXT+="1. **Acknowledgment** - Start of task: \`Bash: .claude/hooks/play-tts.sh \"[action]\" --llm claude-code\`\n"
|
|
40
|
+
CONTEXT+="2. **Completion** - End of task: \`Bash: .claude/hooks/play-tts.sh \"[result + key details]\" --llm claude-code\`\n\n"
|
|
41
|
+
CONTEXT+="**Example:**\n\`\`\`\n[Bash: .claude/hooks/play-tts.sh \"Checking git status\" --llm claude-code]\n[work...]\n"
|
|
42
|
+
CONTEXT+="[Bash: .claude/hooks/play-tts.sh \"Repository is clean, no changes\" --llm claude-code]\n\`\`\`\n\n"
|
|
43
|
+
|
|
44
|
+
# Add verbosity-specific protocol
|
|
45
|
+
case "$VERBOSITY" in
|
|
46
|
+
low)
|
|
47
|
+
CONTEXT+="## Verbosity: LOW\n- Acknowledgment: Action only\n- Completion: Result + errors only\n- Skip: Reasoning, decisions\n\n"
|
|
48
|
+
;;
|
|
49
|
+
medium)
|
|
50
|
+
CONTEXT+="## Verbosity: MEDIUM\n- Acknowledgment: Action + key approach\n- Completion: Result + important decisions\n- Include: Major choices only\n\n"
|
|
51
|
+
;;
|
|
52
|
+
high)
|
|
53
|
+
CONTEXT+="## Verbosity: HIGH\n- Acknowledgment: Action + approach + why\n- Completion: Result + decisions + trade-offs\n- Include: Full reasoning, alternatives\n\n"
|
|
54
|
+
;;
|
|
55
|
+
esac
|
|
56
|
+
|
|
57
|
+
# Add style info and rules
|
|
58
|
+
CONTEXT+="## Style: $STYLE\n\n"
|
|
59
|
+
CONTEXT+="## Rules\n"
|
|
60
|
+
CONTEXT+="1. Never skip acknowledgment TTS\n"
|
|
61
|
+
CONTEXT+="2. Never skip completion TTS\n"
|
|
62
|
+
CONTEXT+="3. Match verbosity level\n"
|
|
63
|
+
CONTEXT+="4. Keep under 150 chars\n"
|
|
64
|
+
CONTEXT+="5. Always include errors\n\n"
|
|
65
|
+
CONTEXT+="Quick Ref: low=action+result | medium=+key decisions | high=+full reasoning"
|
|
66
|
+
|
|
67
|
+
# Add BMAD agent voice routing instructions
|
|
68
|
+
CONTEXT+="\n\n## BMAD Agent Voice Routing\n"
|
|
69
|
+
CONTEXT+="If \`.bmad-agent-context\` exists, check its content:\n\n"
|
|
70
|
+
CONTEXT+="**Single agent mode** (content is an agent ID like \"analyst\"):\n"
|
|
71
|
+
CONTEXT+="Use \`bmad-speak.sh\` instead of \`play-tts.sh\`:\n\n\n"
|
|
72
|
+
CONTEXT+="**Party mode** (content is \"party-mode\"):\n"
|
|
73
|
+
CONTEXT+="Each agent speaks via \`bmad-speak.sh\` with their display name. The queue system ensures sequential playback — agents speak one at a time, not overlapping:\n\n"
|
|
74
|
+
CONTEXT+="IMPORTANT: In party mode, do NOT use \`play-tts.sh\`. Always use \`bmad-speak.sh\` with the agent's display name. Do NOT call multiple bmad-speak.sh in parallel — call them sequentially so the queue processes them in order.\n\n"
|
|
75
|
+
CONTEXT+="If \`.bmad-agent-context\` does NOT exist, use \`play-tts.sh\` as normal."
|
|
76
|
+
|
|
77
|
+
# Escape for JSON (handle newlines, quotes, backslashes)
|
|
78
|
+
ESCAPED=$(printf '%s' "$CONTEXT" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g')
|
|
79
|
+
|
|
80
|
+
# Output structured JSON for reliable context injection
|
|
81
|
+
printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$ESCAPED"
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#
|
|
2
|
+
# File: .claude/hooks-windows/audio-processor.ps1
|
|
3
|
+
#
|
|
4
|
+
# AgentVibes - Windows Audio Effects Processor
|
|
5
|
+
# Applies reverb and background music effects to TTS audio
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
param(
|
|
9
|
+
[Parameter(Position = 0)]
|
|
10
|
+
[string]$InputFile = "",
|
|
11
|
+
|
|
12
|
+
[Parameter(Position = 1)]
|
|
13
|
+
[string]$AgentName = "default",
|
|
14
|
+
|
|
15
|
+
[Parameter(Position = 2)]
|
|
16
|
+
[string]$OutputFile = ""
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
$ErrorActionPreference = "Continue"
|
|
20
|
+
|
|
21
|
+
# Validate inputs
|
|
22
|
+
if (-not $InputFile -or -not (Test-Path $InputFile)) {
|
|
23
|
+
Write-Host "[ERROR] Input file required and must exist" -ForegroundColor Red
|
|
24
|
+
exit 1
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Set default output file
|
|
28
|
+
if (-not $OutputFile) {
|
|
29
|
+
$OutputFile = $InputFile -replace '\.wav$', '-processed.wav'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Configuration paths - prefer local project over global
|
|
33
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
34
|
+
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $ScriptDir)
|
|
35
|
+
|
|
36
|
+
# Resolve project-local config (if project-based)
|
|
37
|
+
$ProjectConfigDir = Join-Path $ProjectRoot ".claude\config"
|
|
38
|
+
$ProjectConfigFile = Join-Path $ProjectConfigDir "audio-effects.cfg"
|
|
39
|
+
|
|
40
|
+
# Global fallback
|
|
41
|
+
$GlobalConfigDir = Join-Path (Split-Path -Parent $ScriptDir) "config"
|
|
42
|
+
$GlobalConfigFile = Join-Path $GlobalConfigDir "audio-effects.cfg"
|
|
43
|
+
|
|
44
|
+
# Use project config if it exists, else fall back to global
|
|
45
|
+
$ConfigFile = if (Test-Path $ProjectConfigFile) { $ProjectConfigFile } else { $GlobalConfigFile }
|
|
46
|
+
$ConfigDir = Split-Path -Parent $ConfigFile
|
|
47
|
+
|
|
48
|
+
$EnabledFile = Join-Path $ConfigDir "background-music-enabled.txt"
|
|
49
|
+
$GlobalEnabledFile = "$env:USERPROFILE\.claude\config\background-music-enabled.txt"
|
|
50
|
+
$BackgroundDir = Join-Path (Split-Path -Parent $ScriptDir) "audio\tracks"
|
|
51
|
+
|
|
52
|
+
# Get effects configuration for agent
|
|
53
|
+
function Get-AgentEffects {
|
|
54
|
+
param([string]$Agent)
|
|
55
|
+
|
|
56
|
+
if (-not (Test-Path $ConfigFile)) {
|
|
57
|
+
return @{reverb = ""; bgFile = ""; bgVol = 0.0}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
$lines = Get-Content $ConfigFile -ErrorAction SilentlyContinue
|
|
61
|
+
$configLine = $null
|
|
62
|
+
|
|
63
|
+
foreach ($line in $lines) {
|
|
64
|
+
if ($line -match "^$([regex]::Escape($Agent))\|") {
|
|
65
|
+
$configLine = $line
|
|
66
|
+
break
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (-not $configLine) {
|
|
71
|
+
foreach ($line in $lines) {
|
|
72
|
+
if ($line -match "^default\|") {
|
|
73
|
+
$configLine = $line
|
|
74
|
+
break
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if ($configLine) {
|
|
80
|
+
$parts = $configLine -split '\|'
|
|
81
|
+
if ($parts.Count -ge 2) {
|
|
82
|
+
return @{
|
|
83
|
+
reverb = $parts[1].Trim()
|
|
84
|
+
bgFile = if ($parts.Count -ge 3) { $parts[2].Trim() } else { "" }
|
|
85
|
+
bgVol = if ($parts.Count -ge 4) { [float]$parts[3] } else { 0.0 }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return @{reverb = ""; bgFile = ""; bgVol = 0.0}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Check if sox and ffmpeg are available
|
|
94
|
+
$SoxAvailable = $null -ne (Get-Command sox -ErrorAction SilentlyContinue)
|
|
95
|
+
$FfmpegAvailable = $null -ne (Get-Command ffmpeg -ErrorAction SilentlyContinue)
|
|
96
|
+
|
|
97
|
+
# Get effects for this agent
|
|
98
|
+
$effects = Get-AgentEffects $AgentName
|
|
99
|
+
|
|
100
|
+
# Check if background music is enabled
|
|
101
|
+
$BgMusicEnabled = $false
|
|
102
|
+
if (Test-Path $EnabledFile) {
|
|
103
|
+
$BgMusicEnabled = (Get-Content $EnabledFile).Trim() -eq "true"
|
|
104
|
+
} elseif (Test-Path $GlobalEnabledFile) {
|
|
105
|
+
$BgMusicEnabled = (Get-Content $GlobalEnabledFile).Trim() -eq "true"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
# Start with the input file
|
|
109
|
+
$CurrentFile = $InputFile
|
|
110
|
+
$NeedsCleanup = $false
|
|
111
|
+
|
|
112
|
+
# Apply reverb using sox if available and configured
|
|
113
|
+
if ($SoxAvailable -and $effects.reverb) {
|
|
114
|
+
$TempFile = "$InputFile.tmp.wav"
|
|
115
|
+
try {
|
|
116
|
+
# Validate reverb params: only allow known sox reverb tokens (numbers, "reverb", "gain", etc.)
|
|
117
|
+
$reverbTokens = $effects.reverb -split ' ' | Where-Object {
|
|
118
|
+
$_ -match '^-?[0-9]+(\.[0-9]+)?$' -or $_ -match '^(reverb|gain|vol|norm|pad|trim|rate|channels)$'
|
|
119
|
+
}
|
|
120
|
+
$soxArgs = @($InputFile) + $reverbTokens + @($TempFile)
|
|
121
|
+
& sox @soxArgs 2>$null
|
|
122
|
+
if (Test-Path $TempFile) {
|
|
123
|
+
$CurrentFile = $TempFile
|
|
124
|
+
$NeedsCleanup = $true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
Write-Host "[WARNING] Sox reverb failed" -ForegroundColor Yellow
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Apply background music mixing if enabled and file specified
|
|
133
|
+
if ($BgMusicEnabled -and $FfmpegAvailable -and $effects.bgFile) {
|
|
134
|
+
$BgFile = Join-Path $BackgroundDir $effects.bgFile
|
|
135
|
+
if (Test-Path $BgFile) {
|
|
136
|
+
$MixedFile = "$InputFile.mixed.wav"
|
|
137
|
+
$BgVolume = [math]::Round($effects.bgVol, 2)
|
|
138
|
+
$TTSVolume = 1.0 # Keep TTS at full volume
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
# Use ffmpeg to mix audio: TTS voice + background music
|
|
142
|
+
# -y to overwrite output file
|
|
143
|
+
$ffArgs = @(
|
|
144
|
+
"-y",
|
|
145
|
+
"-i", $CurrentFile,
|
|
146
|
+
"-i", $BgFile,
|
|
147
|
+
"-filter_complex", "[0]volume=$TTSVolume[a];[1]volume=$BgVolume[b];[a][b]amix=inputs=2:duration=first[out]",
|
|
148
|
+
"-map", "[out]",
|
|
149
|
+
$MixedFile
|
|
150
|
+
)
|
|
151
|
+
& ffmpeg @ffArgs 2>$null
|
|
152
|
+
if ((Test-Path $MixedFile) -and (Get-Item $MixedFile).Length -gt 0) {
|
|
153
|
+
if ($NeedsCleanup -and (Test-Path $CurrentFile) -and $CurrentFile -ne $InputFile) {
|
|
154
|
+
Remove-Item -Path $CurrentFile -Force -ErrorAction SilentlyContinue
|
|
155
|
+
}
|
|
156
|
+
$CurrentFile = $MixedFile
|
|
157
|
+
$NeedsCleanup = $true
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
Write-Host "[WARNING] FFmpeg mixing failed for $($effects.bgFile)" -ForegroundColor Yellow
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# Copy to final output location
|
|
167
|
+
if ($CurrentFile -ne $InputFile -or $CurrentFile -ne $OutputFile) {
|
|
168
|
+
Copy-Item -Path $CurrentFile -Destination $OutputFile -Force -ErrorAction SilentlyContinue
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Cleanup temp files
|
|
172
|
+
if ($NeedsCleanup -and (Test-Path $CurrentFile) -and $CurrentFile -ne $OutputFile) {
|
|
173
|
+
Remove-Item -Path $CurrentFile -Force -ErrorAction SilentlyContinue
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
# Ensure output file exists
|
|
177
|
+
if (-not (Test-Path $OutputFile)) {
|
|
178
|
+
Copy-Item -Path $InputFile -Destination $OutputFile -Force
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Write-Output $OutputFile
|