Versions

  • v79

    5/10/2024
    Open: Version
    Changes from v78 to v79
    +0
    -0
    ⦚ 409 unchanged lines ⦚
    ⦚ 409 unchanged lines ⦚
  • v78

    5/10/2024
    Open: Version
    Changes from v77 to v78
    +99
    -98
    ⦚ 196 unchanged lines ⦚
    audioUrl: '',
    inputLanguage: '',
    startRecording: async function () {
    if (!this.recorder) {
    try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    const mimeType = getSupportedMimeType();
    if (!mimeType) {
    console.error("No supported MIME type found for recording.");
    return;
    }
    this.recorder = new MediaRecorder(stream, { mimeType });
    this.recorder.ondataavailable = (e) => {
    if (e.data && e.data.size > 0) {
    this.chunks.push(e.data);
    }
    };
    this.recorder.onstop = async () => {
    const blob = new Blob(this.chunks, { type: mimeType });
    const formData = new FormData();
    formData.append("audio", blob, "recording.wav");
    const response = await fetch("/transcribe", { method: "POST", body: formData });
    if (response.ok) {
    const result = await response.text();
    this.inputLanguage = result.split("Input Language: ")[1].split("\n")[0];
    this.transcription = result.split("Transcription: ")[1];
    await this.translateText();
    } else {
    const errorMessage = await response.text();
    ⦚ 196 unchanged lines ⦚
    audioUrl: '',
    inputLanguage: '',
    }));
    });

    const startRecording = async function () {
    if (!this.recorder) {
    try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    const mimeType = getSupportedMimeType();

    if (!mimeType) {
    console.error("No supported MIME type found for recording.");
    return;
    }

    this.recorder = new MediaRecorder(stream, { mimeType });

    this.recorder.ondataavailable = (e) => {
    if (e.data && e.data.size > 0) {
    this.chunks.push(e.data);
    }
    };

    this.recorder.onstop = async () => {
    const blob = new Blob(this.chunks, { type: mimeType });
    const formData = new FormData();
    formData.append("audio", blob, "recording.wav");
    const response = await fetch("/transcribe", { method: "POST", body: formData });
    if (response.ok) {
    const result = await response.text();
    this.inputLanguage = result.split("Input Language: ")[1].split("\n")[0];
    this.transcription = result.split("Transcription: ")[1];
  • v77

    5/10/2024
    Open: Version
    Changes from v76 to v77
    +11
    -4
    ⦚ 114 unchanged lines ⦚
    </div>
    <div class="container mx-auto py-8 px-8" x-data="recordingData">
    <h1 class="text-4xl font-bold mb-4">Translator</h1>
    ⦚ 44 unchanged lines ⦚
    <div class="mt-4">
    <div x-show="inputLanguage">
    <h2 class="font-bold mb-2" x-text="'Input Language: ' + inputLanguage"></h2>
    </div>
    <div x-show="transcription">
    ⦚ 9 unchanged lines ⦚
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    ⦚ 106 unchanged lines ⦚
    }));
    });

    // Helper function to get the supported MIME type
    ⦚ 108 unchanged lines ⦚
    ⦚ 114 unchanged lines ⦚
    </div>
    <div class="container mx-auto py-8 px-8" x-data="{
    isRecording: false,
    recorder: null,
    chunks: [],
    transcription: '',
    translation: '',
    translationLanguage: '',
    audioUrl: '',
    inputLanguage: ''
    }">
    <h1 class="text-4xl font-bold mb-4">Translator</h1>
    ⦚ 44 unchanged lines ⦚
    <div class="mt-4">
    <div x-show="inputLanguage">
    <h2 class="font-bold mb-2" x-text="inputLanguage + ':'"></h2>
    </div>
    <div x-show="transcription">
    ⦚ 9 unchanged lines ⦚
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    ⦚ 106 unchanged lines ⦚
    }));
    });
    // Helper function to get the supported MIME type
    ⦚ 108 unchanged lines ⦚
  • v76

    5/10/2024
    Open: Version
    Changes from v75 to v76
    +7
    -6
    ⦚ 177 unchanged lines ⦚
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    isRecording: false,
    ⦚ 32 unchanged lines ⦚
    if (response.ok) {
    const result = await response.text();
    const [inputLanguage, transcription] = result.split("Transcription:");
    this.inputLanguage = inputLanguage.trim().replace("Input Language: ", "");
    this.transcription = transcription ? transcription.trim() : "";
    await this.translateText();
    } else {
    ⦚ 34 unchanged lines ⦚
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
    text: this.transcription,
    language: "Translate the text to the other language in this pair: [" + language1Value + ", " + language2Value + "]. Provide only the translated text. After the translation, identify the target language and return it in the format 'Target Language: <language>'."
    }),
    });
    ⦚ 26 unchanged lines ⦚
    }));
    });
    // Helper function to get the supported MIME type
    ⦚ 108 unchanged lines ⦚
    ⦚ 177 unchanged lines ⦚
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    isRecording: false,
    ⦚ 32 unchanged lines ⦚
    if (response.ok) {
    const result = await response.text();
    this.inputLanguage = result.split("Input Language: ")[1].split("\n")[0];
    this.transcription = result.split("Transcription: ")[1];
    await this.translateText();
    } else {
    ⦚ 34 unchanged lines ⦚
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
    text: this.transcription,
    language: "Translate the text to the other language in this pair: [" + language1Value + ", " + language2Value + "]. Provide only the translated text. After the translation, identify the target language and return it in the format 'Target Language: <language>'."
    }),
    });
    ⦚ 26 unchanged lines ⦚
    }));
    });

    // Helper function to get the supported MIME type
    ⦚ 108 unchanged lines ⦚
  • v75

    5/10/2024
    Open: Version
    Changes from v74 to v75
    +46
    -3
    ⦚ 177 unchanged lines ⦚
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    isRecording: false,
    ⦚ 58 unchanged lines ⦚
    },
    // ... (existing code) ...
    }));
    });

    // Helper function to get the supported MIME type
    ⦚ 108 unchanged lines ⦚
    ⦚ 177 unchanged lines ⦚
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    isRecording: false,
    ⦚ 58 unchanged lines ⦚
    },
    stopRecording: async function () {
    if (this.recorder && this.isRecording) {
    this.recorder.stop();
    this.isRecording = false;
    this.recorder = null;
    }
    },
    translateText: async function () {
    const language1Value = document.getElementById("language1").value;
    const language2Value = document.getElementById("language2").value;
    const response = await fetch("/translate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
    text: this.transcription,
    language: "Translate the text to the other language in this pair: [" + language1Value + ", " + language2Value + "]. Provide only the translated text. After the translation, identify the target language and return it in the format 'Target Language: <language>'."
    }),
    });
    if (response.ok) {
    const result = await response.text();
    const [translation, targetLanguage] = result.split("Target Language:");
    this.translation = translation.trim();
    this.translationLanguage = targetLanguage.trim();
  • v74

    5/10/2024
    Open: Version
    Changes from v73 to v74
    +116
    -2
    ⦚ 84 unchanged lines ⦚
    </head>
    <body>
    <!-- ... (existing code) ... -->
    <script>
    document.addEventListener('alpine:init', () => {
    Alpine.data('recordingData', () => ({
    ⦚ 62 unchanged lines ⦚
    }));
    });
    // ... (existing code) ...
    </script>
    </body>
    ⦚ 84 unchanged lines ⦚
    ⦚ 84 unchanged lines ⦚
    </head>
    <body>
    <div id="startModal" class="fixed z-10 inset-0 overflow-y-auto" x-data="{ showModal: true }" x-show="showModal" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0">
    <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <div class="fixed inset-0 transition-opacity" aria-hidden="true" @click="showModal = false">
    <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
    </div>
    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
    <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" role="dialog" aria-modal="true" aria-labelledby="modal-headline">
    <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
    <div class="sm:flex sm:items-start">
    <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
    <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-headline">
    Enable Microphone Access
    </h3>
    <div class="mt-2">
    <p class="text-sm text-gray-500">
    Please allow microphone access to start recording.
    </p>
    </div>
    </div>
    </div>
    </div>
    <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
    <button type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm" @click="showModal = false">
    Allow Microphone
    </button>
    </div>
    </div>
    </div>
    </div>
    <div class="container mx-auto py-8 px-8" x-data="recordingData">
    <h1 class="text-4xl font-bold mb-4">Translator</h1>
  • v73

    5/10/2024
    Open: Version
    Changes from v72 to v73
    +5
    -162
    ⦚ 84 unchanged lines ⦚
    </head>
    <body>
    <div id="startModal" class="fixed z-10 inset-0 overflow-y-auto" x-data="{ showModal: true }" x-show="showModal" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0">
    <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <div class="fixed inset-0 transition-opacity" aria-hidden="true" @click="showModal = false">
    <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
    </div>
    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
    <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" role="dialog" aria-modal="true" aria-labelledby="modal-headline">
    <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
    <div class="sm:flex sm:items-start">
    <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
    <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-headline">
    Enable Microphone Access
    </h3>
    <div class="mt-2">
    <p class="text-sm text-gray-500">
    Please allow microphone access to start recording.
    </p>
    </div>
    </div>
    </div>
    </div>
    <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
    <button type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm" @click="showModal = false">
    Allow Microphone
    </button>
    </div>
    </div>
    </div>
    </div>
    <div class="container mx-auto py-8 px-8" x-data="recordingData">
    <h1 class="text-4xl font-bold mb-4">Translator</h1>
    ⦚ 84 unchanged lines ⦚
    </head>
    <body>
    <!-- ... (existing code) ... -->
    <script>
    ⦚ 36 unchanged lines ⦚
    const result = await response.text();
    const [inputLanguage, transcription] = result.split("Transcription:");
    this.inputLanguage = inputLanguage.trim().replace("Input Language: ", "");
    this.transcription = transcription ? transcription.trim() : "";
    await this.translateText();
    } else {
    ⦚ 19 unchanged lines ⦚
    },
    // ... (existing code) ...
    }));
    });
    // ... (existing code) ...
    </script>
    </body>
    ⦚ 84 unchanged lines ⦚
  • v72

    5/10/2024
    Open: Version
    Changes from v71 to v72
    +10
    -2
    ⦚ 162 unchanged lines ⦚
    <div class="mt-4">
    <div x-show="transcription">
    <div id="output" class="border border-gray-300 rounded p-4" x-text="transcription"></div>
    </div>
    ⦚ 16 unchanged lines ⦚
    translationLanguage: '',
    audioUrl: '',
    startRecording: async function () {
    ⦚ 22 unchanged lines ⦚
    const response = await fetch("/transcribe", { method: "POST", body: formData });
    if (response.ok) {
    this.transcription = await response.text();
    await this.translateText();
    } else {
    ⦚ 8 unchanged lines ⦚
    this.recorder.start(1000);
    this.isRecording = true;
    this.transcription = '';
    this.translation = '';
    ⦚ 23 unchanged lines ⦚
    body: JSON.stringify({
    text: this.transcription,
    language: "Detect the language of the given text. Then, translate the text to the other language in this pair: [" + language1Value + ", " + language2Value + "]. Provide only the translated text. After the translation, identify the target language and return it in the format 'Target Language: <language>'."
    }),
    });
    ⦚ 138 unchanged lines ⦚
    ⦚ 162 unchanged lines ⦚
    <div class="mt-4">
    <div x-show="inputLanguage">
    <h2 class="font-bold mb-2" x-text="'Input Language: ' + inputLanguage"></h2>
    </div>
    <div x-show="transcription">
    <div id="output" class="border border-gray-300 rounded p-4" x-text="transcription"></div>
    </div>
    ⦚ 16 unchanged lines ⦚
    translationLanguage: '',
    audioUrl: '',
    inputLanguage: '',
    startRecording: async function () {
    ⦚ 22 unchanged lines ⦚
    const response = await fetch("/transcribe", { method: "POST", body: formData });
    if (response.ok) {
    const result = await response.text();
    const [inputLanguage, transcription] = result.split("Transcription:");
    this.inputLanguage = inputLanguage.trim();
    this.transcription = transcription.trim();
    await this.translateText();
    } else {
    ⦚ 8 unchanged lines ⦚
    this.recorder.start(1000);
    this.isRecording = true;
    this.inputLanguage = '';
    this.transcription = '';
    this.translation = '';
    ⦚ 23 unchanged lines ⦚
    body: JSON.stringify({
  • v71

    5/10/2024
    Open: Version
    +392
    -0

    import { Hono } from "npm:hono@3";
    import { html } from "npm:hono@3/html";
    import { cors } from 'npm:hono/cors';
    import { OpenAI } from "npm:openai";

    const app = new Hono();
    const openai = new OpenAI(Deno.env.get("OPENAI_API_KEY_VOICE"));

    class TranscriptionService {
    async transcribeAudio(audioFile) {
    try {
    const transcription = await openai.audio.transcriptions.create({
    file: audioFile,
    model: "whisper-1",
    response_format: "text",
    });

    return transcription;
    } catch (error) {
    console.error('OpenAI API error:', error);
    throw error;
    }
    }
    }

    export const transcriptionService = new TranscriptionService();

    app.use('*', cors({
    origin: '*',
    allowMethods: ['GET', 'POST'],
    allowHeaders: ['Content-Type'],
    }));




yawnxyz-translator.web.val.run
Updated: May 10, 2024