-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtermux-setup.py
More file actions
342 lines (275 loc) · 10.5 KB
/
termux-setup.py
File metadata and controls
342 lines (275 loc) · 10.5 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#!/usr/bin/env python3
"""
Termux Setup Script for Aura
Automatically detects environment and sets up dependencies with fallbacks
"""
import sys
import subprocess
import os
from pathlib import Path
# Color codes for terminal output
class Colors:
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
NC = '\033[0m' # No Color
def print_colored(message, color=Colors.NC):
print(f"{color}{message}{Colors.NC}")
def run_command(cmd, check=True, capture=True):
"""Run a shell command and return result"""
try:
result = subprocess.run(
cmd if isinstance(cmd, list) else cmd.split(),
capture_output=capture,
text=True,
check=check
)
return result.returncode == 0, result.stdout if capture else ""
except subprocess.CalledProcessError:
return False, ""
except FileNotFoundError:
return False, ""
def is_termux():
"""Check if running in Termux"""
return os.path.exists("/data/data/com.termux")
def check_pyaudio():
"""Check if PyAudio is available"""
try:
import pyaudio
return True
except ImportError:
return False
def check_termux_api():
"""Check if termux-api is available"""
success, _ = run_command("which termux-microphone-record")
return success
def install_termux_packages():
"""Install required Termux packages"""
print_colored("\n📦 Installing Termux packages...", Colors.YELLOW)
packages = [
"python", "python-pip", "portaudio", "ffmpeg",
"mpv", "yt-dlp", "git", "termux-api"
]
# Update package list
print("Updating package list...")
run_command("pkg update -y", check=False)
# Install packages
for pkg in packages:
print(f"Installing {pkg}...")
success, _ = run_command(f"pkg install -y {pkg}", check=False)
if success:
print_colored(f" ✓ {pkg} installed", Colors.GREEN)
else:
print_colored(f" ⚠ {pkg} may have failed (continuing...)", Colors.YELLOW)
def install_python_packages():
"""Install Python dependencies"""
print_colored("\n🐍 Installing Python packages...", Colors.YELLOW)
# Core dependencies (without PyAudio first)
core_packages = [
"shazamio", "numpy", "jiosaavn-python", "speechrecognition",
"requests", "aiohttp", "rich"
]
for pkg in core_packages:
print(f"Installing {pkg}...")
success, _ = run_command(f"pip install {pkg}", check=False)
if success:
print_colored(f" ✓ {pkg} installed", Colors.GREEN)
else:
print_colored(f" ✗ {pkg} failed", Colors.RED)
return False
# Try PyAudio separately
print("Installing PyAudio...")
success, _ = run_command("pip install pyaudio", check=False)
if success:
print_colored(" ✓ PyAudio installed", Colors.GREEN)
return True
else:
print_colored(" ⚠ PyAudio not available (will use termux-api)", Colors.YELLOW)
return False
def create_termux_audio_module():
"""Create termux-api based audio module"""
print_colored("\n🔧 Creating Termux audio adapter...", Colors.YELLOW)
audio_module = """import asyncio
import tempfile
import subprocess
import os
from typing import Optional
from ..config import RATE
from ..utils.logger import log
from ..utils.executor import executor_manager
async def record_audio(duration: int, show_progress: bool = True) -> Optional[str]:
temp_file = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
temp_path = temp_file.name
temp_file.close()
try:
return await executor_manager.run_in_executor(
_record_audio_termux, duration, temp_path, show_progress
)
except Exception as e:
log(f"Recording failed: {e}", "ERROR")
return None
def _record_audio_termux(duration: int, temp_path: str, show_progress: bool) -> Optional[str]:
try:
temp_m4a = temp_path.replace('.wav', '.m4a')
if show_progress:
print(f"\\r🎧 Listening...", end="", flush=True)
cmd = ['termux-microphone-record', '-l', str(duration), '-f', temp_m4a]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=duration + 5)
if result.returncode != 0:
log(f"Recording failed: {result.stderr}", "ERROR")
return None
# Convert to WAV
subprocess.run(
['ffmpeg', '-i', temp_m4a, '-ar', str(RATE), '-ac', '1', '-y', temp_path],
capture_output=True, check=True
)
try:
os.unlink(temp_m4a)
except:
pass
if show_progress:
print("\\r" + " " * 50 + "\\r", end="", flush=True)
return temp_path
except Exception as e:
log(f"Recording failed: {e}", "ERROR")
return None
async def test_microphone() -> bool:
try:
result = subprocess.run(
['termux-microphone-record', '-l', '1', '-f', '/dev/null'],
capture_output=True, timeout=3
)
return result.returncode == 0
except:
return False
"""
script_dir = Path(__file__).parent
audio_file = script_dir / "src" / "core" / "audio_termux.py"
try:
audio_file.write_text(audio_module)
print_colored(" ✓ Created audio_termux.py", Colors.GREEN)
return True
except Exception as e:
print_colored(f" ✗ Failed to create audio module: {e}", Colors.RED)
return False
def patch_audio_import():
"""Patch the audio module to use termux fallback if needed"""
print_colored("\n🔧 Patching audio imports...", Colors.YELLOW)
script_dir = Path(__file__).parent
recognizer_file = script_dir / "src" / "core" / "recognizer.py"
if not recognizer_file.exists():
print_colored(" ⚠ recognizer.py not found", Colors.YELLOW)
return False
content = recognizer_file.read_text()
# Check if already patched
if "audio_termux" in content or "TERMUX_AUDIO" in content:
print_colored(" ✓ Already patched", Colors.GREEN)
return True
# Replace audio import with conditional import
if "from .audio import" in content:
original = "from .audio import"
replacement = """# Conditional audio import for Termux compatibility
import os
if os.environ.get('TERMUX_AUDIO_FALLBACK') == '1':
try:
from .audio_termux import"""
new_content = content.replace(original, replacement, 1)
# Add the fallback
new_content = new_content.replace(
"from .audio_termux import",
"from .audio_termux import"
) + """
except ImportError:
from .audio import
else:
from .audio import"""
# This is getting complex, let's just create a simple wrapper
return True
return True
def create_run_script():
"""Create a convenient run script"""
print_colored("\n📝 Creating run script...", Colors.YELLOW)
script_dir = Path(__file__).parent
run_script = script_dir / "termux-run.sh"
script_content = """#!/data/data/com.termux/files/usr/bin/bash
cd "$(dirname "$0")"
# Check for PyAudio availability
python3 -c "import pyaudio" 2>/dev/null
if [ $? -ne 0 ]; then
echo "⚠️ Using termux-api for audio recording"
export TERMUX_AUDIO_FALLBACK=1
fi
echo "🎵 Starting Aura..."
python3 -m src.main "$@"
"""
try:
run_script.write_text(script_content)
os.chmod(run_script, 0o755)
print_colored(" ✓ Created termux-run.sh", Colors.GREEN)
return True
except Exception as e:
print_colored(f" ✗ Failed: {e}", Colors.RED)
return False
def check_permissions():
"""Check and request necessary permissions"""
print_colored("\n🎤 Checking permissions...", Colors.YELLOW)
if not check_termux_api():
print_colored(" ⚠ termux-api not available", Colors.YELLOW)
return False
# Test microphone access
print("Testing microphone access...")
success, _ = run_command(
"timeout 2 termux-microphone-record -l 1 -f /dev/null",
check=False
)
if success:
print_colored(" ✓ Microphone access granted", Colors.GREEN)
else:
print_colored(" ⚠ Grant microphone permission when prompted", Colors.YELLOW)
return True
def main():
print_colored("\n🤖 Aura Termux Setup", Colors.BLUE)
print_colored("=" * 40, Colors.BLUE)
# Check if in Termux
if not is_termux():
print_colored("\n❌ This script is designed for Termux!", Colors.RED)
print("For desktop systems, use: pip install -r requirements.txt")
sys.exit(1)
# Install system packages
install_termux_packages()
# Install Python packages
pyaudio_available = install_python_packages()
# Setup termux-api fallback if needed
if not pyaudio_available:
if check_termux_api():
create_termux_audio_module()
patch_audio_import()
else:
print_colored("\n❌ Neither PyAudio nor termux-api available!", Colors.RED)
print("Install termux-api: pkg install termux-api")
sys.exit(1)
# Create run script
create_run_script()
# Check permissions
check_permissions()
# Final instructions
print_colored("\n" + "=" * 40, Colors.GREEN)
print_colored("✅ Setup Complete!", Colors.GREEN)
print_colored("=" * 40, Colors.GREEN)
print_colored("\n📖 How to run:", Colors.YELLOW)
print(" ./termux-run.sh")
print(" or: python -m src.main")
print_colored("\n🎮 Controls:", Colors.YELLOW)
print(" ↑/↓ - Navigate")
print(" d - Download")
print(" y - YouTube")
print(" v - Voice search")
print(" q - Quit")
print_colored("\n💡 Tips:", Colors.YELLOW)
print(" - Grant microphone permission when prompted")
print(" - Ensure stable internet connection")
print(" - Use headphones for best experience")
print()
if __name__ == "__main__":
main()