HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/glive/app.py
# app.py

import os
import argparse
import asyncio
import json
import ssl

from aiohttp import web, WSMsgType
import base64
from aiortc import RTCPeerConnection, RTCSessionDescription, VideoStreamTrack, AudioStreamTrack
from aiortc.contrib.media import MediaBlackhole, MediaRecorder
import cv2

from google import genai

# Set up Google GenAI client
client = genai.Client(http_options={"api_version": "v1alpha"})
CONFIG = {"generation_config": {"response_modalities": ["AUDIO"]}}
MODEL = "models/gemini-2.0-flash-exp"

pcs = set()

async def websocket_handler(request):
      ws = web.WebSocketResponse()
      await ws.prepare(request)

      # Store the websocket for communication
      ws_id = id(ws)
      request.app['websockets'][ws_id] = ws

      async for msg in ws:
          if msg.type == WSMsgType.TEXT:
              # Handle incoming messages if necessary
              pass
          elif msg.type == WSMsgType.ERROR:
              print(f'WebSocket connection closed with exception {ws.exception()}')

      # Clean up
      del request.app['websockets'][ws_id]
      return ws

async def index(request):
    content = open('index.html', 'r').read()
    return web.Response(content_type='text/html', text=content)

async def javascript(request):
    content = open('client.js', 'r').read()
    return web.Response(content_type='application/javascript', text=content)

async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params['sdp'], type=params['type'])

    pc = RTCPeerConnection()
    pcs.add(pc)

    # Handle video track
    @pc.on('track')
    async def on_track(track):
        print('Track %s received' % track.kind)
        if track.kind == 'video':
            local_video = VideoFrameProcessorTrack(track, request.app)
            pc.addTrack(local_video)
        elif track.kind == 'audio':
            local_audio = AudioProcessorTrack(track, request.app)
            pc.addTrack(local_audio)
        pass

        @track.on('ended')
        async def on_ended():
            print('Track %s ended' % track.kind)

    await pc.setRemoteDescription(offer)

    # Send back an answer
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type='application/json',
        text=json.dumps(
            {'sdp': pc.localDescription.sdp, 'type': pc.localDescription.type}
        )
    )

async def on_shutdown(app):
    # Close all peer connections
    coros = [pc.close() for pc in pcs]
    await asyncio.gather(*coros)
    pcs.clear()

async def process_image_with_genai(image, app):
    # Convert image to bytes
    _, buffer = cv2.imencode('.jpg', image)
    image_bytes = buffer.tobytes()
    image_base64 = base64.b64encode(image_bytes).decode()

    frame_data = {"mime_type": "image/jpeg", "data": image_base64}

    # Use the Google GenAI client
    async with client.aio.live.connect(model=MODEL, config=CONFIG) as session:
        await session.send(frame_data)

        # Receive and process the response
        turn = session.receive()
        async for response in turn:
            if data := response.data:
                # Send data back to client via WebSocket
                message = {"type": "data", "data": base64.b64encode(data).decode()}
            if message_text := response.text:
                message = {"type": "text", "text": message_text}

            # Send message to all connected clients
            for ws in app['websockets'].values():
                await ws.send_json(message)

async def process_audio_with_genai(audio_data, app):
    # Prepare audio data
    audio_base64 = base64.b64encode(audio_data).decode()
    audio_frame = {"mime_type": "audio/pcm", "data": audio_base64}

    # Use the Google GenAI client
    async with client.aio.live.connect(model=MODEL, config=CONFIG) as session:
        await session.send(audio_frame)

        # Receive and process the response
        turn = session.receive()
        async for response in turn:
            if data := response.data:
                # Send data back to client via WebSocket
                message = {"type": "data", "data": base64.b64encode(data).decode()}
            if message_text := response.text:
                message = {"type": "text", "text": message_text}

            # Send message to all connected clients
            for ws in app['websockets'].values():
                await ws.send_json(message)

class VideoFrameProcessorTrack(VideoStreamTrack):
    """
    A video track that processes frames from another track.
    """
    def __init__(self, track, app):
        super().__init__()
        self.track = track
        self.app = app

    async def recv(self):
        frame = await self.track.recv()

        # Convert to OpenCV image
        img = frame.to_ndarray(format="bgr24")

        # Process the image with GenAI
        await process_image_with_genai(img, self.app)

        return frame

class AudioProcessorTrack(AudioStreamTrack):
     def __init__(self, track, app):
         super().__init__()
         self.track = track
         self.app = app

     async def recv(self):
         frame = await self.track.recv()
         audio_data = frame.to_bytes()

         # Process the audio frame with GenAI
         await process_audio_with_genai(audio_data, self.app)

         return frame  # Echo back if needed

def main():
    parser = argparse.ArgumentParser(description='WebRTC video stream')
    parser.add_argument('--host', default='0.0.0.0', help='Host to listen on (default: 0.0.0.0)')
    parser.add_argument('--port', type=int, default=8237, help='Port to listen on (default: 8237)')
    parser.add_argument('--cert', help='SSL certificate file (for HTTPS)')
    parser.add_argument('--key', help='SSL key file (for HTTPS)')
    args = parser.parse_args()

    app = web.Application()
    app['websockets'] = {}

    # Add the websocket route
    app.router.add_get('/ws', websocket_handler)
    app.on_shutdown.append(on_shutdown)
    app.router.add_get('/', index)
    app.router.add_get('/client.js', javascript)
    app.router.add_post('/offer', offer)

    # SSL context for HTTPS
    ssl_context = None
    if args.cert and args.key:
        ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
        ssl_context.load_cert_chain(args.cert, args.key)

    web.run_app(app, host=args.host, port=args.port, ssl_context=ssl_context)

if __name__ == '__main__':
    main()