177 lines
6.6 KiB
Plaintext
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>
|