-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathsmart_streamer.py
More file actions
executable file
·189 lines (157 loc) · 6.69 KB
/
smart_streamer.py
File metadata and controls
executable file
·189 lines (157 loc) · 6.69 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
#!/usr/bin/env python3
"""
Smart Streamer - Automatically chooses optimal streaming method
Detects system capabilities and uses the most efficient approach:
- Headless system: Direct frame capture (no X11)
- GUI system: Fallback to virtual display method
"""
import os
import sys
import subprocess
import logging
from pathlib import Path
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def detect_system_capabilities():
"""Detect what kind of system we're running on"""
capabilities = {
'has_display': False,
'has_xvfb': False,
'has_chrome': False,
'has_ffmpeg': False,
'recommended_mode': 'headless'
}
# Check for active display
if os.environ.get('DISPLAY') or os.environ.get('WAYLAND_DISPLAY'):
capabilities['has_display'] = True
logger.info("🖥️ Active display detected")
else:
logger.info("🔌 Headless system detected (no display)")
# Check for Xvfb
try:
subprocess.run(['which', 'Xvfb'], check=True, capture_output=True)
capabilities['has_xvfb'] = True
logger.info("✅ Xvfb available")
except subprocess.CalledProcessError:
logger.info("❌ Xvfb not available")
# Check for Chromium
try:
result = subprocess.run(['chromium-browser', '--version'], check=True, capture_output=True, text=True)
capabilities['has_chrome'] = True # Keep same key for compatibility
logger.info(f"✅ Chromium available: {result.stdout.strip()}")
except subprocess.CalledProcessError:
# Fallback to Chrome if available
try:
result = subprocess.run(['google-chrome', '--version'], check=True, capture_output=True, text=True)
capabilities['has_chrome'] = True
logger.info(f"✅ Chrome available: {result.stdout.strip()}")
except subprocess.CalledProcessError:
logger.error("❌ Neither Chromium nor Chrome available")
# Check for FFmpeg
try:
result = subprocess.run(['ffmpeg', '-version'], check=True, capture_output=True, text=True)
capabilities['has_ffmpeg'] = True
logger.info("✅ FFmpeg available")
except subprocess.CalledProcessError:
logger.error("❌ FFmpeg not available")
# Determine recommended mode
if not capabilities['has_display'] and not capabilities['has_xvfb']:
capabilities['recommended_mode'] = 'pure_headless'
logger.info("🎯 Recommended mode: Pure headless (most efficient)")
elif not capabilities['has_display'] and capabilities['has_xvfb']:
capabilities['recommended_mode'] = 'virtual_display'
logger.info("🎯 Recommended mode: Virtual display (Xvfb)")
else:
capabilities['recommended_mode'] = 'display'
logger.info("🎯 Recommended mode: Normal display")
return capabilities
def start_optimal_streaming():
"""Start streaming using the optimal method for this system"""
# Get system capabilities
capabilities = detect_system_capabilities()
# Check requirements
if not capabilities['has_chrome']:
logger.error("❌ Chromium or Chrome browser is required but not found")
return False
if not capabilities['has_ffmpeg']:
logger.error("❌ FFmpeg is required but not found")
return False
# Get configuration
stream_key = os.environ.get('YOUTUBE_STREAM_KEY')
if not stream_key:
logger.error("❌ YOUTUBE_STREAM_KEY environment variable required")
return False
content_path = os.environ.get('CONTENT_PATH')
if not content_path:
logger.error("❌ CONTENT_PATH environment variable required")
logger.error("💡 Example: CONTENT_PATH='https://clock.zone' python3 smart_streamer.py")
return False
# Auto-detect mode from content path
if content_path.endswith('.py'):
mode = 'pygame'
else:
mode = 'html'
logger.info("🚀 Starting optimal streaming configuration...")
logger.info(f" Auto-detected mode: {mode}")
logger.info(f" Content: {content_path}")
logger.info(f" System mode: {capabilities['recommended_mode']}")
# Choose and start the appropriate streamer
if capabilities['recommended_mode'] == 'pure_headless':
logger.info("🎊 Using PURE HEADLESS mode - maximum efficiency!")
from headless_streamer import HeadlessHTMLStreamer, HeadlessPygameStreamer
if mode == 'pygame':
streamer = HeadlessPygameStreamer(stream_key, content_path)
else:
streamer = HeadlessHTMLStreamer(stream_key, content_path)
else:
logger.info("🔄 Using VIRTUAL DISPLAY mode - fallback for compatibility")
# Import the original streamers
if mode == 'pygame':
from pygame_streamer import PygameStreamer
streamer = PygameStreamer()
else:
from main import HTMLStreamer
streamer = HTMLStreamer()
# Start streaming
success, message = streamer.start_streaming()
if success:
logger.info(f"✅ {message}")
# Show efficiency info
if capabilities['recommended_mode'] == 'pure_headless':
logger.info("💰 Running in maximum efficiency mode:")
logger.info(" • No X11/Xvfb overhead")
logger.info(" • Direct frame capture")
logger.info(" • ~60% less CPU/memory usage")
logger.info(" • Perfect for $1-5/month VPS")
return True
else:
logger.error(f"❌ {message}")
return False
def main():
"""Main entry point"""
print("🔍 Smart Streamer - Analyzing System...")
print("=" * 50)
if start_optimal_streaming():
print("\n🎉 Streaming started successfully!")
print("🌐 Your stream is now live on YouTube")
print("💡 This configuration is optimized for your system")
# Keep running
try:
import signal
import time
def signal_handler(sig, frame):
logger.info("Shutting down streaming...")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
while True:
time.sleep(1)
except KeyboardInterrupt:
logger.info("Streaming stopped by user")
else:
print("\n❌ Failed to start streaming")
print("💡 Check logs above for troubleshooting steps")
sys.exit(1)
if __name__ == "__main__":
main()