| 
1 | 1 | <!DOCTYPE html>  | 
2 | 2 | <head>  | 
 | 3 | +    <meta name="viewport" content="width=device-width, initial-scale=1">  | 
 | 4 | +    <style>  | 
 | 5 | +        body {  | 
 | 6 | +            margin: 0;  | 
 | 7 | +            padding: 0;  | 
 | 8 | +            font-family: Arial, sans-serif;  | 
 | 9 | +            background: #f9f9f9;  | 
 | 10 | +        }  | 
 | 11 | +        .container {  | 
 | 12 | +            max-width: 600px;  | 
 | 13 | +            margin: 2rem auto;  | 
 | 14 | +            padding: 1rem;  | 
 | 15 | +            background: #fff;  | 
 | 16 | +            border-radius: 8px;  | 
 | 17 | +            box-shadow: 0 2px 8px rgba(0,0,0,0.05);  | 
 | 18 | +            display: flex;  | 
 | 19 | +            flex-direction: column;  | 
 | 20 | +            align-items: center;  | 
 | 21 | +        }  | 
 | 22 | +        audio {  | 
 | 23 | +            width: 100%;  | 
 | 24 | +            max-width: 500px;  | 
 | 25 | +            margin-bottom: 1.5rem;  | 
 | 26 | +        }  | 
 | 27 | +        .controls {  | 
 | 28 | +            width: 100%;  | 
 | 29 | +            display: flex;  | 
 | 30 | +            flex-direction: column;  | 
 | 31 | +            gap: 0.75rem;  | 
 | 32 | +        }  | 
 | 33 | +        .controls input[type="text"] {  | 
 | 34 | +            width: 100%;  | 
 | 35 | +            padding: 0.5rem;  | 
 | 36 | +            font-size: 1rem;  | 
 | 37 | +            border: 1px solid #ccc;  | 
 | 38 | +            border-radius: 4px;  | 
 | 39 | +        }  | 
 | 40 | +        .controls button {  | 
 | 41 | +            padding: 0.75rem;  | 
 | 42 | +            font-size: 1rem;  | 
 | 43 | +            border: none;  | 
 | 44 | +            border-radius: 5px;  | 
 | 45 | +            background: #4CAF50; /* Modern green */  | 
 | 46 | +            color: #fff;  | 
 | 47 | +            cursor: pointer;  | 
 | 48 | +            transition: background 0.2s;  | 
 | 49 | +        }  | 
 | 50 | +        .controls button:hover:enabled {  | 
 | 51 | +            background: #388E3C; /* Slightly darker green for hover */  | 
 | 52 | +        }  | 
 | 53 | +        .controls button.close-btn {  | 
 | 54 | +            background: #F44336; /* Modern red */  | 
 | 55 | +            color: #fff;  | 
 | 56 | +        }  | 
 | 57 | +        .controls button.close-btn:hover:enabled {  | 
 | 58 | +            background: #C62828; /* Slightly darker red for hover */  | 
 | 59 | +        }  | 
 | 60 | +        .controls button:disabled {  | 
 | 61 | +            opacity: 0.6;  | 
 | 62 | +            cursor: not-allowed;  | 
 | 63 | +        }  | 
 | 64 | +        @media (max-width: 600px) {  | 
 | 65 | +            .container {  | 
 | 66 | +                margin: 0;  | 
 | 67 | +                border-radius: 0;  | 
 | 68 | +                box-shadow: none;  | 
 | 69 | +            }  | 
 | 70 | +            audio {  | 
 | 71 | +                max-width: 100%;  | 
 | 72 | +            }  | 
 | 73 | +        }  | 
 | 74 | +    </style>  | 
3 | 75 |     <script type="text/javascript">  | 
4 | 76 |         const WEBSOCKET_URL = "ws://127.0.0.1:8080/ws"  | 
5 | 77 |         const STUN_URL = "stun:stun.cloudflare.com";  | 
 | 
17 | 89 |         }  | 
18 | 90 | 
 
  | 
19 | 91 |         async function start() {  | 
 | 92 | +            document.getElementById('startBtn').disabled = true;  | 
 | 93 | +            document.getElementById('closeBtn').disabled = false;  | 
20 | 94 |             pc = new RTCPeerConnection({  | 
21 | 95 |                 iceServers: [  | 
22 | 96 |                     {  | 
 | 
34 | 108 |             });  | 
35 | 109 | 
 
  | 
36 | 110 |             pc.ontrack = evt => {  | 
37 |  | -                console.log("Adding track to video control.");  | 
38 |  | -                document.querySelector('#videoCtl').srcObject = evt.streams[0];  | 
 | 111 | +                console.log("Adding track to audio control.");  | 
 | 112 | +                document.querySelector('#audioCtl').srcObject = evt.streams[0];  | 
39 | 113 | 
 
  | 
40 | 114 |                 evt.streams[0].onunmute = () => {  | 
41 |  | -                    console.log("Adding track to video control.");  | 
 | 115 | +                    console.log("Adding track to audio control.");  | 
42 | 116 |                 };  | 
43 | 117 | 
 
  | 
44 | 118 |                 evt.streams[0].onended = () => {  | 
 | 
78 | 152 |         };  | 
79 | 153 | 
 
  | 
80 | 154 |         async function closePeer() {  | 
 | 155 | +            document.getElementById('startBtn').disabled = false;  | 
 | 156 | +            document.getElementById('closeBtn').disabled = true;  | 
81 | 157 |             await pc?.close();  | 
82 | 158 |             await ws?.close();  | 
83 | 159 | 
 
  | 
 | 
90 | 166 |     </script>  | 
91 | 167 | </head>  | 
92 | 168 | <body>  | 
93 |  | - | 
94 |  | -    <video controls autoplay="autoplay" id="videoCtl" width="640" height="480"></video>  | 
95 |  | - | 
96 |  | -    <div>  | 
97 |  | -        <input type="text" id="websockurl" size="40" />  | 
98 |  | -        <button type="button" class="btn btn-success" onclick="start();">Start</button>  | 
99 |  | -        <button type="button" class="btn btn-success" onclick="closePeer();">Close</button>  | 
 | 169 | +    <div class="container">  | 
 | 170 | +        <audio controls autoplay id="audioCtl"></audio>  | 
 | 171 | +        <div class="controls">  | 
 | 172 | +            <input type="text" id="websockurl" size="40" />  | 
 | 173 | +            <button type="button" class="btn btn-success" id="startBtn" onclick="start();">Start</button>  | 
 | 174 | +            <button type="button" class="btn close-btn" id="closeBtn" onclick="closePeer();" disabled>Close</button>  | 
 | 175 | +        </div>  | 
100 | 176 |     </div>  | 
101 |  | - | 
102 | 177 | </body>  | 
103 | 178 | 
 
  | 
104 | 179 | <script>  | 
 | 
0 commit comments