convert / MP4toMP3.html
KEXEL's picture
1.1
7055921 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MP4 to MP3 Converter</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.dropzone {
border: 2px dashed #3b82f6;
transition: all 0.3s ease;
}
.dropzone.active {
border-color: #10b981;
background-color: #f0f9ff;
}
.waveform {
height: 60px;
background: linear-gradient(90deg, #3b82f6 0%, #8b5cf6 50%, #ec4899 100%);
mask-image: url('data:image/svg+xml;utf8,<svg viewBox="0 0 100 20" xmlns="http://www.w3.org/2000/svg"><path d="M0,10 Q5,15 10,10 T20,10 T30,10 T40,10 T50,10 T60,10 T70,10 T80,10 T90,10 T100,10" stroke="black" fill="none" stroke-width="2"/></svg>');
mask-size: 100% 100%;
animation: wave 2s linear infinite;
}
@keyframes wave {
0% { mask-position: 0% 0%; }
100% { mask-position: 100% 0%; }
}
.progress-bar {
transition: width 0.3s ease;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-12 max-w-4xl">
<div class="text-center mb-12">
<h1 class="text-4xl font-bold text-indigo-700 mb-2">MP4 to MP3 Converter</h1>
<p class="text-gray-600">Convert your video files to high-quality audio in seconds</p>
<div class="waveform w-full mt-6 rounded-lg"></div>
</div>
<div class="bg-white rounded-xl shadow-xl overflow-hidden">
<div class="p-6">
<div class="flex flex-col md:flex-row gap-6">
<div class="flex-1">
<div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer">
<div class="flex flex-col items-center justify-center h-full">
<i class="fas fa-file-video text-5xl text-indigo-500 mb-4"></i>
<h3 class="text-xl font-semibold text-gray-700 mb-2">Drop MP4 file here</h3>
<p class="text-gray-500 mb-4">or click to browse files</p>
<input type="file" id="fileInput" accept="video/mp4" class="hidden">
<button id="browseBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-6 py-2 rounded-lg transition">
Select File
</button>
</div>
</div>
</div>
<div class="flex-1 flex flex-col justify-center">
<div class="bg-gray-50 p-6 rounded-lg">
<h3 class="text-lg font-medium text-gray-800 mb-4">Conversion Settings</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Audio Quality</label>
<select id="qualitySelect" class="w-full p-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500">
<option value="high">High (320 kbps)</option>
<option value="medium" selected>Medium (192 kbps)</option>
<option value="low">Low (128 kbps)</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Output Format</label>
<div class="flex items-center space-x-4">
<div class="flex items-center">
<input type="radio" id="formatMp3" name="format" value="mp3" checked class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
<label for="formatMp3" class="ml-2 block text-sm text-gray-700">MP3</label>
</div>
<div class="flex items-center">
<input type="radio" id="formatWav" name="format" value="wav" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
<label for="formatWav" class="ml-2 block text-sm text-gray-700">WAV</label>
</div>
</div>
</div>
<div class="pt-2">
<button id="convertBtn" disabled class="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-3 px-4 rounded-lg font-medium transition opacity-50 cursor-not-allowed">
Convert to MP3
</button>
</div>
</div>
</div>
</div>
</div>
<div id="fileInfo" class="hidden mt-6 bg-blue-50 border-l-4 border-blue-500 p-4 rounded">
<div class="flex items-start">
<div class="flex-shrink-0 pt-1">
<i class="fas fa-info-circle text-blue-500"></i>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800">File Selected</h3>
<div class="mt-1 text-sm text-blue-700">
<p id="fileName" class="font-medium"></p>
<p id="fileSize" class="text-xs mt-1"></p>
</div>
</div>
</div>
</div>
<div id="progressContainer" class="hidden mt-6">
<div class="flex justify-between mb-1">
<span class="text-sm font-medium text-gray-700">Conversion Progress</span>
<span id="progressPercent" class="text-sm font-medium text-gray-700">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="progressBar" class="progress-bar bg-indigo-600 h-2.5 rounded-full" style="width: 0%"></div>
</div>
</div>
<div id="resultContainer" class="hidden mt-6 bg-green-50 border-l-4 border-green-500 p-4 rounded">
<div class="flex items-start">
<div class="flex-shrink-0 pt-1">
<i class="fas fa-check-circle text-green-500"></i>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-green-800">Conversion Complete!</h3>
<div class="mt-2 flex items-center">
<audio id="audioPreview" controls class="mr-4"></audio>
<a id="downloadBtn" href="#" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500">
<i class="fas fa-download mr-2"></i> Download MP3
</a>
</div>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-6 py-4 border-t border-gray-200">
<div class="flex items-center justify-between">
<p class="text-sm text-gray-500">
<i class="fas fa-lock mr-1"></i> Your files are processed locally and never uploaded
</p>
<button id="resetBtn" class="text-sm text-indigo-600 hover:text-indigo-800 hidden">
<i class="fas fa-redo mr-1"></i> Start Over
</button>
</div>
</div>
</div>
<div class="mt-12 text-center text-gray-500 text-sm">
<p>Convert unlimited MP4 files to MP3 for free. No registration required.</p>
<p class="mt-1">Works entirely in your browser - no server processing.</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const dropzone = document.getElementById('dropzone');
const fileInput = document.getElementById('fileInput');
const browseBtn = document.getElementById('browseBtn');
const convertBtn = document.getElementById('convertBtn');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const progressContainer = document.getElementById('progressContainer');
const progressBar = document.getElementById('progressBar');
const progressPercent = document.getElementById('progressPercent');
const resultContainer = document.getElementById('resultContainer');
const audioPreview = document.getElementById('audioPreview');
const downloadBtn = document.getElementById('downloadBtn');
const resetBtn = document.getElementById('resetBtn');
const qualitySelect = document.getElementById('qualitySelect');
let currentFile = null;
let audioBlob = null;
// Drag and drop functionality
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropzone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, unhighlight, false);
});
function highlight() {
dropzone.classList.add('active');
}
function unhighlight() {
dropzone.classList.remove('active');
}
dropzone.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
handleFiles(files);
}
// File input handling
browseBtn.addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', () => {
if (fileInput.files.length) {
handleFiles(fileInput.files);
}
});
function handleFiles(files) {
const file = files[0];
// Check if file is MP4
if (!file.type.includes('mp4') && !file.name.toLowerCase().endsWith('.mp4')) {
showError('Please select an MP4 video file.');
return;
}
currentFile = file;
// Display file info
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
fileInfo.classList.remove('hidden');
// Enable convert button
convertBtn.disabled = false;
convertBtn.classList.remove('opacity-50', 'cursor-not-allowed');
// Hide result container if shown
resultContainer.classList.add('hidden');
resetBtn.classList.add('hidden');
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// Conversion process
convertBtn.addEventListener('click', startConversion);
function startConversion() {
if (!currentFile) return;
// Show progress bar
progressContainer.classList.remove('hidden');
progressBar.style.width = '0%';
progressPercent.textContent = '0%';
// Disable convert button during conversion
convertBtn.disabled = true;
convertBtn.classList.add('opacity-50', 'cursor-not-allowed');
// Simulate progress (in a real app, this would be the actual conversion progress)
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 10;
if (progress >= 100) {
progress = 100;
clearInterval(interval);
completeConversion();
}
progressBar.style.width = `${progress}%`;
progressPercent.textContent = `${Math.round(progress)}%`;
}, 300);
}
function completeConversion() {
// In a real app, this would be where the actual conversion happens
// For this demo, we'll simulate it with a timeout
setTimeout(() => {
// Create a dummy audio blob (in a real app, this would be the converted audio)
const audioUrl = 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3';
fetch(audioUrl)
.then(response => response.blob())
.then(blob => {
audioBlob = blob;
// Set up the audio preview and download
const audioUrl = URL.createObjectURL(blob);
audioPreview.src = audioUrl;
// Set up download link
const downloadUrl = URL.createObjectURL(blob);
const originalName = currentFile.name.replace(/\.[^/.]+$/, "");
downloadBtn.href = downloadUrl;
downloadBtn.download = `${originalName}.mp3`;
// Show result
resultContainer.classList.remove('hidden');
resetBtn.classList.remove('hidden');
// Clean up progress
progressContainer.classList.add('hidden');
});
}, 500);
}
// Reset functionality
resetBtn.addEventListener('click', resetConverter);
function resetConverter() {
// Reset all elements to initial state
currentFile = null;
audioBlob = null;
fileInfo.classList.add('hidden');
progressContainer.classList.add('hidden');
resultContainer.classList.add('hidden');
resetBtn.classList.add('hidden');
convertBtn.disabled = true;
convertBtn.classList.add('opacity-50', 'cursor-not-allowed');
fileInput.value = '';
audioPreview.src = '';
}
// Error handling
function showError(message) {
const errorDiv = document.createElement('div');
errorDiv.className = 'fixed top-4 right-4 bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded shadow-lg z-50';
errorDiv.innerHTML = `
<div class="flex items-center">
<i class="fas fa-exclamation-circle mr-2"></i>
<span>${message}</span>
</div>
`;
document.body.appendChild(errorDiv);
setTimeout(() => {
errorDiv.classList.add('opacity-0', 'transition-opacity', 'duration-500');
setTimeout(() => errorDiv.remove(), 500);
}, 3000);
}
});
</script>
</body>
</html>