Untitled
/* eslint-disable react/jsx-no-target-blank */ /* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable no-unused-vars */ import { Col, Input, Row } from 'antd'; import React, { useEffect, useRef, useState } from 'react'; import { Form } from 'react-bootstrap'; import { microphone, microphone2 } from '../icons/icon'; const Translater = () => { const [microphones, setMicrophones] = useState([]); const [speakers, setSpeakers] = useState([]); const [output1, setOutput1] = useState(''); const [output2, setOutput2] = useState(''); const [originalText1, setOriginalText1] = useState(''); const [originalText2, setOriginalText2] = useState(''); const [webSocket, setWebSocket] = useState(null); const [recording, setRecording] = useState(false); const [formData, setFormData] = useState({ microphone: '', target_output_1: '', target_output_2: '' }); const mediaRecorderRef = useRef(null); const audioPlayerRef1 = useRef(null); const audioPlayerRef2 = useRef(null); useEffect(() => { const getMediaDevices = async () => { let stream = null; try { stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); const devices = await navigator.mediaDevices.enumerateDevices(); const microphones = devices.filter(device => device.kind === 'audioinput'); const speakers = devices.filter(device => device.kind === 'audiooutput'); setMicrophones(microphones); setSpeakers(speakers); } catch (error) { console.error('Error getting media devices:', error); } finally { if (stream) { stream.getTracks().forEach(track => track.stop()); } } }; getMediaDevices(); }, []); const handleChange = (e) => { const { name, value } = e.target; setFormData(prevData => ({ ...prevData, [name]: value })); }; // Function to play audio const playAudio = async (audioDataUrl, outputRef, speakerId) => { if (outputRef.current) { try { await outputRef.current.setSinkId(speakerId); } catch (error) { console.error('Error setting sink ID:', error); } outputRef.current.src = audioDataUrl; outputRef.current.play(); } }; // Function to setup WebSocket connection const setupWebSocket = () => { return new Promise((resolve, reject) => { const ws = new WebSocket('wss://apex-bff.azurewebsites.net/Translation/ws'); ws.onopen = () => { resolve(ws); }; ws.onclose = (event) => { setWebSocket(null); }; ws.onerror = (error) => { reject(error); }; ws.onmessage = (event) => { try { console.log(event.data); const message = JSON.parse(event.data); const mimeType = 'audio/wav'; const audioDataUrl = `data:${mimeType};base64,${message.TranslatedAudio}`; console.log(message); if (message.TranslateLanguage === 'en') { setOutput1(prevText => `${prevText} ${message.TranslatedText}`); setOriginalText1(prevText => `${prevText} ${message.Originaltext}`); playAudio(audioDataUrl, audioPlayerRef1, formData.target_output_1); } else if (message.TranslateLanguage === 'es') { setOutput2(prevText => `${prevText} ${message.TranslatedText}`); setOriginalText2(prevText => `${prevText} ${message.Originaltext}`); playAudio(audioDataUrl, audioPlayerRef2, formData.target_output_2); } } catch (e) { console.error('Error processing WebSocket message:', e); } }; setWebSocket(ws); }); }; // PCM16 conversion function const floatTo16BitPCM = (input) => { const buffer = new ArrayBuffer(input.length * 2); const view = new DataView(buffer); for (let i = 0; i < input.length; i++) { let s = Math.max(-1, Math.min(1, input[i])); s = s < 0 ? s * 0x8000 : s * 0x7FFF; view.setInt16(i * 2, s, true); } return buffer; }; // Function to start recording const startRecording = async () => { if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') { return; } try { const ws = await setupWebSocket(); const stream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: formData.microphone ? { exact: formData.microphone } : undefined } }); const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const source = audioContext.createMediaStreamSource(stream); const processor = audioContext.createScriptProcessor(4096, 1, 1); processor.onaudioprocess = (event) => { if (ws && ws.readyState === WebSocket.OPEN) { const inputData = event.inputBuffer.getChannelData(0); const pcm16Data = floatTo16BitPCM(inputData); ws.send(pcm16Data); } }; source.connect(processor); processor.connect(audioContext.destination); mediaRecorderRef.current = processor; setRecording(true); } catch (error) { console.error('Error starting recording:', error); } }; const stopRecording = () => { if (mediaRecorderRef.current) { mediaRecorderRef.current.disconnect(); } if (webSocket) { webSocket.close(); } setRecording(false); }; const handleSubmit = (e) => { e.preventDefault(); if (recording) { stopRecording(); } else { startRecording(); } }; return ( <main className='lg:container py-3 px-3 px-md-5 mx-auto' style={{ minHeight: '88vh' }}> <h2 className='roboto_regular text_black'>Translator</h2> <div className="bg_white shadow-sm rounded-3 px-3 px-md-5 py-4"> <Form onSubmit={handleSubmit} className="mx-auto w-100 my-4"> <div className="flex flex-col w-full"> <div className="flex flex-col mb-3 gap-2 w-full justify-center items-center"> <button type="submit"> <img src={recording ? microphone : microphone2} style={{ width: '140px', height: '140px' }} alt="Microphone" /> </button> <span className="roboto_regular mb-3 text_dark text-lg">{recording ? 'Microphone capturing....' : 'Initiate Translation Session'}</span> <div className="flex flex-col items-start" style={{ width: '100%', maxWidth: '500px' }}> <span className='roboto_regular mb-1 text_secondary w-full'>Choose Input Microphone</span> <Form.Select name='microphone' size='large' className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" onChange={handleChange} > <option value=''>Default Microphone</option> {microphones.length > 0 ? microphones.map((mic) => ( <option key={mic.deviceId} value={mic.deviceId}> {mic.label || 'Unnamed Microphone'} </option> )) : <option value="">No Microphones Found</option>} </Form.Select> </div> </div> <Row gutter={16}> <Col xs={24} md={12}> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Choose a Target Language 1*</span> <Form.Group name='target_language_1'> <Form.Control size='large' value='English' readOnly className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" /> </Form.Group> </div> </Col> <Col xs={24} md={12}> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Choose a Target Language 2</span> <Form.Group name='target_language_2'> <Form.Control size='large' value='Spanish' readOnly className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" /> </Form.Group> </div> </Col> </Row> <Row gutter={16}> <Col xs={24} md={12}> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Choose a Target Output 1*</span> <Form.Select size="large" required={!recording} name='target_output_1' className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" onChange={handleChange} > <option value="">Select Speaker</option> {speakers.length > 0 ? speakers.map((speaker) => ( <option key={speaker.deviceId} value={speaker.deviceId}> {speaker.label || 'Unnamed Speaker'} </option> )) : <option value="">No Speakers Found</option>} </Form.Select> </div> </Col> <Col xs={24} md={12}> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Choose a Target Output 2</span> <Form.Select size="large" required={!recording} name='target_output_2' className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" onChange={handleChange} > <option value="">Select Speaker</option> {speakers.length > 0 ? speakers.map((speaker) => ( <option key={speaker.deviceId} value={speaker.deviceId}> {speaker.label || 'Unnamed Speaker'} </option> )) : <option value="">No Speakers Found</option>} </Form.Select> </div> </Col> </Row> <Row gutter={16}> <Col xs={24} md={12}> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Translated Output 1</span> <Input.TextArea rows={4} className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" value={output1} readOnly /> <audio ref={audioPlayerRef1} controls style={{ display: 'none' }}> Your browser does not support the audio element. </audio> {/* <button onClick={() => alert(originalText1)} className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" style={{ marginTop: '10px' }}> Show Original Text </button> */} </div> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Orignal Text 1</span> <Input.TextArea rows={4} className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" value={originalText1} readOnly /> </div> </Col> <Col xs={24} md={12}> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Translated Output 2</span> <Input.TextArea rows={4} className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" value={output2} readOnly /> <audio ref={audioPlayerRef2} style={{ display: 'none' }} controls> Your browser does not support the audio element. </audio> {/* <button onClick={() => alert(originalText2)} className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" style={{ marginTop: '10px' }}> Show Original Text </button> */} </div> <div className="flex flex-col mb-3 w-full"> <span className='roboto_regular mb-1 text_secondary w-full'>Orignal Text 2</span> <Input.TextArea rows={4} className="custom_control rounded-3 manrope_regular text_secondarydark bg_white border" value={originalText2} readOnly /> </div> </Col> </Row> </div> </Form> </div> </main> ); }; export default Translater;
Leave a Comment