Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Piper ONNX Converter</title> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen flex flex-col items-center justify-center"> | |
| <div class="container mx-auto px-4 flex-grow"> | |
| <h1 class="text-3xl font-bold mb-8 text-center">Piper ONNX Converter</h1> | |
| <form id="converterForm" class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"> | |
| <div class="mb-4"> | |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="repo_id"> | |
| Hugging Face Repository ID: | |
| </label> | |
| <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="repo_id" name="repo_id" type="text" required> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="token"> | |
| Hugging Face Token: | |
| </label> | |
| <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="token" name="token" type="password" required> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="model_name"> | |
| Model Name: | |
| </label> | |
| <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="model_name" name="model_name" type="text" required> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="submit"> | |
| Convert and Download | |
| </button> | |
| </div> | |
| </form> | |
| <div id="progress" class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4" style="display: none;"> | |
| <h2 class="text-2xl font-bold mb-4">Processing...</h2> | |
| <div id="log" class="bg-gray-100 p-4 rounded-lg h-64 overflow-y-auto mb-4"></div> | |
| <a id="downloadLink" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" style="display: none;">Download Converted Model</a> | |
| <button id="convertAnotherButton" class="bg-yellow-500 hover:bg-yellow-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" style="display: none;">Convert Another Model</button> | |
| </div> | |
| </div> | |
| <footer class="w-full text-center py-4 bg-gray-200 text-gray-600 text-sm"> | |
| <p>Con amor by <a href="https://hircoir.eu.org" class="text-blue-500 hover:underline">HirCoir</a> - <a href="https://github.com/HirCoir" class="text-blue-500 hover:underline">GitHub</a></p> | |
| </footer> | |
| <script> | |
| const form = document.getElementById('converterForm'); | |
| const progress = document.getElementById('progress'); | |
| const log = document.getElementById('log'); | |
| const downloadLink = document.getElementById('downloadLink'); | |
| const convertAnotherButton = document.getElementById('convertAnotherButton'); | |
| const socket = io(); | |
| socket.on('task_update', function(data) { | |
| const logEntry = document.createElement('p'); | |
| logEntry.textContent = data.message; | |
| log.appendChild(logEntry); | |
| log.scrollTop = log.scrollHeight; | |
| // Check if the message contains the download URL | |
| if (data.message.includes("Processing completed. Download URL:")) { | |
| const url = data.message.split("Download URL: ")[1]; | |
| downloadLink.href = url; | |
| downloadLink.style.display = 'inline-block'; | |
| convertAnotherButton.style.display = 'inline-block'; | |
| } | |
| }); | |
| form.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const formData = new FormData(form); | |
| try { | |
| const response = await fetch('/', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (data.task_id) { | |
| form.style.display = 'none'; | |
| progress.style.display = 'block'; | |
| pollStatus(data.task_id); | |
| } | |
| } catch (error) { | |
| console.error('Error:', error); | |
| } | |
| }); | |
| async function pollStatus(taskId) { | |
| while (true) { | |
| try { | |
| const response = await fetch(`/status/${taskId}`); | |
| const data = await response.json(); | |
| if (data.status === 'completed') { | |
| // We don't need to set the download link here anymore | |
| // as it's now handled in the socket.on('task_update') function | |
| break; | |
| } else if (data.status === 'error') { | |
| const errorMsg = document.createElement('p'); | |
| errorMsg.textContent = 'An error occurred during processing.'; | |
| errorMsg.classList.add('text-red-500', 'font-bold'); | |
| log.appendChild(errorMsg); | |
| break; | |
| } | |
| await new Promise(resolve => setTimeout(resolve, 5000)); // Poll every 5 seconds | |
| } catch (error) { | |
| console.error('Error polling status:', error); | |
| break; | |
| } | |
| } | |
| } | |
| convertAnotherButton.addEventListener('click', () => { | |
| form.style.display = 'block'; | |
| progress.style.display = 'none'; | |
| downloadLink.style.display = 'none'; | |
| convertAnotherButton.style.display = 'none'; | |
| log.innerHTML = ''; // Clear the log | |
| }); | |
| </script> | |
| </body> | |
| </html> | |