Code viewer for World: Azure Image Description Ge...
// Initialization check to prevent multiple runs
if (!window.initialized) {
  window.initialized = true;

  // Global variables
  let mediaRecorder;
  let audioChunks = [];
  let openaiApiKey = '';
  let otherApiUrl = '';

  // Use document.write to output the complete HTML content, including DOCTYPE declaration
  document.open(); // Explicitly open the document
  document.write(`<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Multilingual Speech Transcription Comparison</title>
  <style>
    /* Global styles */
    body {
      font-family: 'Orbitron', sans-serif;
      background: url('https://wallpaperaccess.com/full/317501.jpg') no-repeat center center fixed;
      background-size: cover;
      margin: 0;
      padding: 0;
      color: #ffffff;
    }
    h1 {
      text-align: center;
      color: #00ffff;
      font-size: 3em;
      margin-top: 20px;
      text-shadow: 0 0 10px #00ffff;
    }
    #container {
      max-width: 1000px;
      margin: 50px auto;
      background: rgba(0, 0, 0, 0.7);
      padding: 30px;
      border-radius: 15px;
      box-shadow: 0 0 20px rgba(0,0,0,0.5);
    }
    #controls {
      margin-bottom: 30px;
    }
    #controls label {
      display: block;
      font-size: 1.2em;
      margin-bottom: 5px;
      width: 100%;
    }
    .input-group {
      width: 100%;
      margin-bottom: 20px;
    }
    #controls input {
      width: 100%;
      padding: 10px;
      font-size: 1em;
      border: none;
      border-radius: 5px;
      background: rgba(255, 255, 255, 0.1);
      color: #ffffff;
      box-sizing: border-box;
    }
    #controls input::placeholder {
      color: #cccccc;
    }
    #start-btn {
      display: block;
      margin: 0 auto 20px auto;
      padding: 15px 50px;
      font-size: 1.5em;
      background: linear-gradient(45deg, #00ffff, #0066ff);
      color: #ffffff;
      border: none;
      border-radius: 10px;
      cursor: pointer;
      box-shadow: 0 0 15px #00ffff;
      transition: all 0.3s ease;
    }
    #start-btn:hover {
      box-shadow: 0 0 25px #00ffff;
    }
    .status {
      text-align: center;
      font-size: 1.2em;
      margin-bottom: 30px;
      text-shadow: 0 0 5px #ffffff;
    }
    /* Adjust result box styles */
    #results {
      margin-bottom: 30px;
    }
    .result-box {
      width: 90%; /* Set result box width to 90% */
      max-width: 800px; /* Set maximum width */
      margin: 0 auto 30px auto; /* Center and add bottom margin */
      background: rgba(255, 255, 255, 0.1);
      padding: 20px;
      border: 1px solid #00ffff;
      border-radius: 10px;
      word-break: break-all;
      box-shadow: 0 0 10px #00ffff;
      position: relative;
      overflow: hidden;
    }
    .result-box h3 {
      margin-top: 0;
      color: #00ffff;
      font-size: 1.5em;
      text-shadow: 0 0 5px #00ffff;
    }
    .result-content {
      max-height: 200px;
      overflow-y: auto;
      padding-right: 10px;
    }
    /* Custom scrollbar */
    .result-content::-webkit-scrollbar {
      width: 8px;
    }
    .result-content::-webkit-scrollbar-thumb {
      background: rgba(0, 255, 255, 0.5);
      border-radius: 4px;
    }
    .loading {
      display: none;
      margin: 0 auto 30px auto;
      border: 8px solid rgba(255, 255, 255, 0.1);
      border-top: 8px solid #00ffff;
      border-radius: 50%;
      width: 80px;
      height: 80px;
      animation: spin 1s linear infinite;
      box-shadow: 0 0 15px #00ffff;
    }
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    .diff-mark {
      text-decoration: underline;
      text-decoration-color: red;
      text-decoration-thickness: 2px;
    }
  </style>
  <!-- Include Google Fonts -->
  <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
  <div id="container">
    <h1>Multilingual Speech Transcription Comparison</h1>
    <div id="controls">
      <div class="input-group">
        <label for="openai-api-key">OpenAI API Key:</label>
        <input type="password" id="openai-api-key" placeholder="Enter your OpenAI API Key">
      </div>
      <div class="input-group">
        <label for="other-api-url">Other API URL:</label>
        <input type="text" id="other-api-url" placeholder="Enter the URL of another speech-to-text API">
      </div>
    </div>
    <p class="status">Click the "Start Recording" button to begin speech transcription.</p>
    <button id="start-btn">Start Recording</button>
    <div class="loading"></div>
    <div id="results">
      <div class="result-box">
        <h3>Web Speech API Transcription</h3>
        <div class="result-content" id="resultContent1"></div>
      </div>
      <div class="result-box">
        <h3>OpenAI Whisper Transcription</h3>
        <div class="result-content" id="resultContent2"></div>
      </div>
      <div class="result-box">
        <h3>Other API Transcription</h3>
        <div class="result-content" id="resultContent3"></div>
      </div>
      <div class="result-box">
        <h3>Comparison Result</h3>
        <div class="result-content" id="comparisonResult"></div>
      </div>
    </div>
  </div>
  <script>
    (function() {
      // Define the compareTranscripts function
      function compareTranscripts(text1, text2, text3) {
        function generateComparisonHtml(textA, textB) {
          const wordsA = textA.split(/\s+/);
          const wordsB = textB.split(/\s+/);
          let resultHtml = '';

          for (let i = 0; i < Math.max(wordsA.length, wordsB.length); i++) {
            if (wordsA[i] !== wordsB[i]) {
              if (wordsA[i]) {
                resultHtml += '<span class="diff-mark">' + wordsA[i] + '</span> ';
              }
              if (wordsB[i]) {
                resultHtml += '<span class="diff-mark">' + wordsB[i] + '</span> ';
              }
            } else {
              resultHtml += wordsA[i] ? wordsA[i] + ' ' : '';
            }
          }

          return resultHtml;
        }

        // Compare text1 and text2, then text1 and text3
        let comparisonHtml = '';

        if (text1 && text2) {
          comparisonHtml += '<h4>Comparison with OpenAI Whisper Transcription</h4>';
          comparisonHtml += generateComparisonHtml(text1, text2);
        }

        if (text1 && text3) {
          comparisonHtml += '<h4>Comparison with Other API Transcription</h4>';
          comparisonHtml += generateComparisonHtml(text1, text3);
        }

        document.getElementById('comparisonResult').innerHTML = comparisonHtml;
      }

      // Other variables and function definitions
      let recognizing = false;
      let recognition;
      let transcript1 = ''; // Web Speech API transcription
      let transcript2 = ''; // OpenAI transcription
      let transcript3 = ''; // Other API transcription

      const startButton = document.getElementById('start-btn');
      const statusText = document.querySelector('.status');
      const loadingSpinner = document.querySelector('.loading');
      const resultContent1 = document.getElementById('resultContent1');
      const resultContent2 = document.getElementById('resultContent2');
      const resultContent3 = document.getElementById('resultContent3');
      const openaiApiKeyInput = document.getElementById('openai-api-key');
      const otherApiUrlInput = document.getElementById('other-api-url');

      // Get microphone permission and initialize MediaRecorder
      navigator.mediaDevices.getUserMedia({ audio: true })
        .then(stream => {
          mediaRecorder = new MediaRecorder(stream);

          mediaRecorder.ondataavailable = event => {
            audioChunks.push(event.data);
          };

          mediaRecorder.onstop = () => {
            const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
            // Upload audio to APIs
            uploadAudioToAPIs(audioBlob);
          };
        })
        .catch(error => {
          console.error('Cannot access microphone:', error);
          statusText.textContent = 'Cannot access microphone: ' + error.message;
          startButton.disabled = true;
        });

      if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
        statusText.textContent = 'Sorry, your browser does not support speech recognition. Please use Chrome or Edge.';
        startButton.disabled = true;
      } else {
        const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
        recognition = new SpeechRecognition();
        recognition.continuous = true;
        recognition.interimResults = true;
        recognition.lang = 'zh-CN'; // Set language, modify as needed

        recognition.onstart = function() {
          recognizing = true;
          transcript1 = '';
          resultContent1.textContent = '';
        };

        recognition.onerror = function(event) {
          console.error('Recognition error:', event.error);
          statusText.textContent = 'Recognition error: ' + event.error;
        };

        recognition.onend = function() {
          recognizing = false;
          console.log('Web Speech API recognition ended');
        };

        recognition.onresult = function(event) {
          let interimTranscript = '';
          for (let i = event.resultIndex; i < event.results.length; ++i) {
            if (event.results[i].isFinal) {
              transcript1 += event.results[i][0].transcript;
            } else {
              interimTranscript += event.results[i][0].transcript;
            }
          }
          resultContent1.textContent = transcript1 + interimTranscript;
        };
      }

      startButton.addEventListener('click', function() {
        if (recognizing) {
          recognition.stop();
          mediaRecorder.stop();
          startButton.textContent = 'Start Recording';
          statusText.textContent = 'Recording stopped.';
          return;
        }
        audioChunks = []; // Clear the array

        // Get user input for OpenAI API Key and Other API URL
        openaiApiKey = openaiApiKeyInput.value.trim();
        otherApiUrl = otherApiUrlInput.value.trim();

        if (!openaiApiKey) {
          statusText.textContent = 'Please enter your OpenAI API Key.';
          return;
        }

        recognizing = true;
        startButton.textContent = 'Stop Recording';
        statusText.textContent = 'Recording... Please speak.';
        transcript1 = '';
        transcript2 = '';
        transcript3 = '';
        resultContent1.textContent = '';
        resultContent2.textContent = '';
        resultContent3.textContent = '';

        recognition.start();
        mediaRecorder.start();
      });

      // Upload audio to OpenAI Whisper API and Other API
      function uploadAudioToAPIs(audioBlob) {
        statusText.textContent = 'Transcribing using OpenAI Whisper API and Other API, please wait...';
        loadingSpinner.style.display = 'block';

        // Reset counters
        let apisFinished = 0;
        const totalApis = otherApiUrl ? 2 : 1;

        // Call OpenAI Whisper API
        uploadAudioToOpenAI(audioBlob, function(transcript) {
          transcript2 = transcript;
          resultContent2.textContent = transcript2;
          checkIfAllAPIsFinished();
        }, function(error) {
          resultContent2.textContent = 'Transcription failed: ' + error.message;
          checkIfAllAPIsFinished();
        });

        // If Other API URL is provided, call it
        if (otherApiUrl) {
          uploadAudioToOtherAPI(audioBlob, otherApiUrl, function(transcript) {
            transcript3 = transcript;
            resultContent3.textContent = transcript3;
            checkIfAllAPIsFinished();
          }, function(error) {
            resultContent3.textContent = 'Transcription failed: ' + error.message;
            checkIfAllAPIsFinished();
          });
        }

        function checkIfAllAPIsFinished() {
          apisFinished++;
          if (apisFinished === totalApis) {
            statusText.textContent = 'Transcription completed.';
            loadingSpinner.style.display = 'none';
            compareTranscripts(transcript1, transcript2, transcript3);
          }
        }
      }

      // Function to upload audio to OpenAI Whisper API
      function uploadAudioToOpenAI(audioBlob, onSuccess, onError) {
        const formData = new FormData();
        formData.append('file', audioBlob, 'recording.webm');
        formData.append('model', 'whisper-1');
        formData.append('response_format', 'json');
        formData.append('language', '');

        fetch('https://api.openai.com/v1/audio/transcriptions', {
          method: 'POST',
          headers: {
            'Authorization': 'Bearer ' + openaiApiKey
          },
          body: formData
        })
        .then(response => {
          console.log('OpenAI Response Status:', response.status);
          if (!response.ok) {
            return response.text().then(text => {
              throw new Error('OpenAI API error! status: ' + response.status + '\\n' + text);
            });
          }
          return response.json();
        })
        .then(data => {
          if (data.error) {
            throw new Error('OpenAI API returned an error: ' + data.error.message);
          }
          onSuccess(data.text);
        })
        .catch(error => {
          console.error('Failed to upload audio to OpenAI API:', error);
          onError(error);
        });
      }

      // Function to upload audio to Other API
      function uploadAudioToOtherAPI(audioBlob, apiUrl, onSuccess, onError) {
        const formData = new FormData();
        formData.append('file', audioBlob, 'recording.webm');

        fetch(apiUrl, {
          method: 'POST',
          body: formData
        })
        .then(response => {
          console.log('Other API Response Status:', response.status);
          const contentType = response.headers.get('content-type');
          if (!response.ok) {
            return response.text().then(text => {
              throw new Error('HTTP error! status: ' + response.status + '\\n' + text);
            });
          }
          if (contentType && contentType.includes('application/json')) {
            return response.json();
          } else {
            return response.text().then(text => {
              throw new Error('Expected JSON, got:\\n' + text);
            });
          }
        })
        .then(data => {
          if (data.error) {
            throw new Error('Server returned an error: ' + data.error);
          }
          onSuccess(data.transcript);
        })
        .catch(error => {
          console.error('Failed to upload audio to Other API:', error);
          onError(error);
        });
      }

    })();
  </script>
</body>
</html>
`);
  document.close(); // Explicitly close the document
}