mirror of
https://github.com/iAmInActions/random-scripts.git
synced 2024-11-24 05:00:15 +00:00
141 lines
5.1 KiB
Python
141 lines
5.1 KiB
Python
|
import socket
|
||
|
import sys
|
||
|
import os
|
||
|
import pyaudio
|
||
|
import threading
|
||
|
import argparse
|
||
|
import struct
|
||
|
import termios
|
||
|
import tty
|
||
|
|
||
|
# Global variable for volume control
|
||
|
volume = 1.0
|
||
|
|
||
|
def play_audio(audio_socket):
|
||
|
""" Function to continuously play audio data received from the server """
|
||
|
global volume
|
||
|
p = pyaudio.PyAudio()
|
||
|
stream = p.open(format=pyaudio.paUInt8, # 8-bit unsigned format
|
||
|
channels=1, # Mono audio
|
||
|
rate=8000, # 8000 Hz sample rate
|
||
|
output=True)
|
||
|
|
||
|
try:
|
||
|
while True:
|
||
|
audio_chunk = audio_socket.recv(1024)
|
||
|
if not audio_chunk:
|
||
|
break
|
||
|
# Adjust the volume of the audio chunk
|
||
|
adjusted_chunk = bytes(min(int(sample * volume), 255) for sample in audio_chunk)
|
||
|
stream.write(adjusted_chunk)
|
||
|
except Exception as e:
|
||
|
print(f"Error playing audio: {e}")
|
||
|
finally:
|
||
|
stream.stop_stream()
|
||
|
stream.close()
|
||
|
p.terminate()
|
||
|
|
||
|
def handle_key_input(video_socket, audio_socket):
|
||
|
""" Function to handle key input for quitting and volume control """
|
||
|
global volume
|
||
|
|
||
|
# Save the terminal settings
|
||
|
original_settings = termios.tcgetattr(sys.stdin)
|
||
|
tty.setcbreak(sys.stdin.fileno()) # Set the terminal to cbreak mode for unbuffered input
|
||
|
|
||
|
try:
|
||
|
while True:
|
||
|
key = sys.stdin.read(1) # Read a single character
|
||
|
if key.lower() == 'q': # Quit on 'q' or 'Q'
|
||
|
print("Quitting...")
|
||
|
video_socket.close()
|
||
|
audio_socket.close()
|
||
|
break
|
||
|
elif key == '+': # Increase volume on '+'
|
||
|
volume = min(volume + 0.1, 2.0) # Cap volume at 2.0
|
||
|
print(f"Volume increased to {volume}")
|
||
|
elif key == '-': # Decrease volume on '-'
|
||
|
volume = max(volume - 0.1, 0.0) # Floor volume at 0.0
|
||
|
print(f"Volume decreased to {volume}")
|
||
|
finally:
|
||
|
# Restore the terminal settings
|
||
|
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, original_settings)
|
||
|
|
||
|
def main():
|
||
|
parser = argparse.ArgumentParser(description="ASCII Video Client")
|
||
|
parser.add_argument("video_url", help="URL of the video to stream")
|
||
|
parser.add_argument("server_ip", help="IP address of the server")
|
||
|
parser.add_argument("port", type=int, help="Port number of the server")
|
||
|
parser.add_argument("contrast", type=float, nargs="?", default=1.0, help="Contrast adjustment (default: 1.0)")
|
||
|
parser.add_argument("brightness", type=float, nargs="?", default=0.0, help="Brightness adjustment (default: 0.0)")
|
||
|
parser.add_argument("-c", "--color", action="store_true", help="Enable color mode using ANSI color codes")
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
# Get the terminal size
|
||
|
terminal_size = os.get_terminal_size()
|
||
|
width = terminal_size.columns
|
||
|
height = terminal_size.lines
|
||
|
|
||
|
# Connect to the server for video
|
||
|
try:
|
||
|
video_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
|
video_socket.connect((args.server_ip, args.port))
|
||
|
print("Connected to video server successfully.")
|
||
|
except Exception as e:
|
||
|
print(f"Failed to connect to video server: {e}")
|
||
|
return
|
||
|
|
||
|
# Send the video URL, contrast, brightness, color flag, and terminal size
|
||
|
color_mode = "1" if args.color else "0"
|
||
|
video_socket.send(f"{args.video_url} {args.contrast} {args.brightness} {color_mode} {width} {height}".encode())
|
||
|
|
||
|
# Connect to the server for audio
|
||
|
try:
|
||
|
audio_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
|
audio_socket.connect((args.server_ip, args.port + 1))
|
||
|
print("Connected to audio server successfully.")
|
||
|
except Exception as e:
|
||
|
print(f"Failed to connect to audio server: {e}")
|
||
|
return
|
||
|
|
||
|
# Start a separate thread for playing audio
|
||
|
audio_thread = threading.Thread(target=play_audio, args=(audio_socket,))
|
||
|
audio_thread.start()
|
||
|
|
||
|
# Handle key input in the main thread
|
||
|
key_thread = threading.Thread(target=handle_key_input, args=(video_socket, audio_socket))
|
||
|
key_thread.start()
|
||
|
|
||
|
try:
|
||
|
while True:
|
||
|
# Receive the frame size
|
||
|
frame_size_data = video_socket.recv(4)
|
||
|
if not frame_size_data:
|
||
|
break
|
||
|
frame_size = struct.unpack("I", frame_size_data)[0]
|
||
|
|
||
|
# Receive the full frame data
|
||
|
frame_data = b""
|
||
|
while len(frame_data) < frame_size:
|
||
|
chunk = video_socket.recv(frame_size - len(frame_data))
|
||
|
if not chunk:
|
||
|
print("Failed to receive full frame data. Connection may be closed.")
|
||
|
return
|
||
|
frame_data += chunk
|
||
|
|
||
|
# Clear the terminal and display the frame
|
||
|
os.system('clear' if os.name == 'posix' else 'cls')
|
||
|
print(frame_data.decode(), end="\r")
|
||
|
except Exception as e:
|
||
|
print(f"Error during video reception: {e}")
|
||
|
finally:
|
||
|
video_socket.close()
|
||
|
audio_socket.close()
|
||
|
audio_thread.join()
|
||
|
key_thread.join()
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|
||
|
|