Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/Extras/VoiceRecorder.cshtml

177 lines
6.6 KiB
Plaintext

@{
Layout = "_ConfigurePlugin";
}
@await Component.InvokeAsync("StoreScopeConfiguration")
<form asp-action="ReceiveVoiceRecording" asp-controller="FruitBankAdmin" method="post">
@Html.AntiForgeryToken()
</form>
<div class="card card-default">
<div class="card-body">
<h4>Voice Recorder</h4>
<p>Click the button below to start recording your voice message.</p>
<div class="form-group row">
<div class="col-md-9">
<button type="button" id="recordButton" class="btn btn-primary">
<i class="fas fa-microphone"></i> Start Recording
</button>
<button type="button" id="stopButton" class="btn btn-danger" style="display:none;">
<i class="fas fa-stop"></i> Stop Recording
</button>
<span id="recordingStatus" style="margin-left: 15px; font-weight: bold;"></span>
</div>
</div>
<div class="form-group row" id="audioPlaybackSection" style="display:none;">
<div class="col-md-9">
<audio id="audioPlayback" controls style="width: 100%;"></audio>
</div>
</div>
<div class="form-group row" id="sendSection" style="display:none;">
<div class="col-md-9">
<button type="button" id="sendButton" class="btn btn-success">
<i class="fas fa-paper-plane"></i> Send to API
</button>
</div>
</div>
<div class="form-group row">
<div class="col-md-9">
<div id="responseMessage" class="alert" style="display:none;"></div>
<div id="transcriptionResult" style="display:none; margin-top: 15px;">
<h5>Transcription:</h5>
<div class="card">
<div class="card-body">
<p id="transcriptionText" style="white-space: pre-wrap;"></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
let mediaRecorder;
let audioChunks = [];
let audioBlob;
const recordButton = document.getElementById('recordButton');
const stopButton = document.getElementById('stopButton');
const sendButton = document.getElementById('sendButton');
const recordingStatus = document.getElementById('recordingStatus');
const audioPlayback = document.getElementById('audioPlayback');
const audioPlaybackSection = document.getElementById('audioPlaybackSection');
const sendSection = document.getElementById('sendSection');
const responseMessage = document.getElementById('responseMessage');
const transcriptionResult = document.getElementById('transcriptionResult');
const transcriptionText = document.getElementById('transcriptionText');
recordButton.addEventListener('click', async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
audioChunks = [];
mediaRecorder.ondataavailable = (event) => {
audioChunks.push(event.data);
};
mediaRecorder.onstop = () => {
audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
const audioUrl = URL.createObjectURL(audioBlob);
audioPlayback.src = audioUrl;
audioPlaybackSection.style.display = 'block';
sendSection.style.display = 'block';
// Stop all tracks to release the microphone
stream.getTracks().forEach(track => track.stop());
};
mediaRecorder.start();
recordButton.style.display = 'none';
stopButton.style.display = 'inline-block';
recordingStatus.textContent = 'Recording...';
recordingStatus.style.color = 'red';
audioPlaybackSection.style.display = 'none';
sendSection.style.display = 'none';
} catch (error) {
console.error('Error accessing microphone:', error);
showMessage('Error: Could not access microphone. Please check permissions.', 'danger');
}
});
stopButton.addEventListener('click', () => {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
recordButton.style.display = 'inline-block';
stopButton.style.display = 'none';
recordingStatus.textContent = 'Recording stopped';
recordingStatus.style.color = 'green';
}
});
sendButton.addEventListener('click', async () => {
if (!audioBlob) {
showMessage('No audio recorded yet!', 'warning');
return;
}
const formData = new FormData();
formData.append('audioFile', audioBlob, 'recording.webm');
try {
sendButton.disabled = true;
sendButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
// Get the antiforgery token
const token = document.querySelector('input[name="__RequestVerificationToken"]').value;
const response = await fetch('@Url.Action("ReceiveVoiceRecording", "FruitBankAudio")', {
method: 'POST',
headers: {
'RequestVerificationToken': token
},
body: formData
});
const result = await response.json();
if (response.ok && result.success) {
showMessage('Audio transcribed successfully!', 'success');
// Display transcription
if (result.transcription) {
transcriptionText.textContent = result.transcription;
transcriptionResult.style.display = 'block';
}
} else {
showMessage('Error: ' + (result.message || 'Failed to transcribe audio'), 'danger');
}
} catch (error) {
console.error('Error sending audio:', error);
showMessage('Error: Failed to send audio to server', 'danger');
} finally {
sendButton.disabled = false;
sendButton.innerHTML = '<i class="fas fa-paper-plane"></i> Send to API';
}
});
function showMessage(message, type) {
responseMessage.textContent = message;
responseMessage.className = 'alert alert-' + type;
responseMessage.style.display = 'block';
setTimeout(() => {
responseMessage.style.display = 'none';
}, 5000);
}
</script>