Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Noise Reducer - Remove Crowd Noise</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --primary: #6366f1; | |
| --primary-hover: #4f46e5; | |
| --secondary: #10b981; | |
| --secondary-hover: #059669; | |
| --bg-dark: #0f172a; | |
| --bg-card: #1e293b; | |
| --bg-card-hover: #334155; | |
| --bg-elevated: #283548; | |
| --text-primary: #f8fafc; | |
| --text-secondary: #94a3b8; | |
| --border: #334155; | |
| --gradient-1: #6366f1; | |
| --gradient-2: #8b5cf6; | |
| --gradient-3: #06b6d4; | |
| --danger: #ef4444; | |
| --danger-hover: #dc2626; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background: var(--bg-dark); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| /* Animated Background */ | |
| .bg-pattern { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: -1; | |
| background: | |
| radial-gradient(ellipse at 20% 20%, rgba(99, 102, 241, 0.15) 0%, transparent 50%), | |
| radial-gradient(ellipse at 80% 80%, rgba(139, 92, 246, 0.1) 0%, transparent 50%), | |
| radial-gradient(ellipse at 50% 50%, rgba(6, 182, 212, 0.05) 0%, transparent 70%); | |
| } | |
| .container { | |
| max-width: 900px; | |
| margin: 0 auto; | |
| padding: 2rem 1.5rem; | |
| } | |
| /* Header */ | |
| header { | |
| text-align: center; | |
| margin-bottom: 3rem; | |
| } | |
| .logo { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| margin-bottom: 1rem; | |
| } | |
| .logo-icon { | |
| width: 48px; | |
| height: 48px; | |
| background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2)); | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| box-shadow: 0 8px 32px rgba(99, 102, 241, 0.3); | |
| } | |
| .logo-icon svg { | |
| width: 28px; | |
| height: 28px; | |
| color: white; | |
| } | |
| h1 { | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| background: linear-gradient(135deg, var(--text-primary), var(--text-secondary)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 0.5rem; | |
| } | |
| .subtitle { | |
| color: var(--text-secondary); | |
| font-size: 1.1rem; | |
| } | |
| .built-with { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| margin-top: 1rem; | |
| padding: 0.5rem 1rem; | |
| background: rgba(99, 102, 241, 0.1); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| border-radius: 20px; | |
| font-size: 0.85rem; | |
| color: var(--primary); | |
| text-decoration: none; | |
| transition: all 0.3s ease; | |
| } | |
| .built-with:hover { | |
| background: rgba(99, 102, 241, 0.2); | |
| transform: translateY(-2px); | |
| } | |
| /* Main Card */ | |
| .main-card { | |
| background: var(--bg-card); | |
| border-radius: 24px; | |
| padding: 2rem; | |
| border: 1px solid var(--border); | |
| box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); | |
| } | |
| /* Upload Section */ | |
| .upload-section { | |
| border: 2px dashed var(--border); | |
| border-radius: 16px; | |
| padding: 3rem 2rem; | |
| text-align: center; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .upload-section::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(139, 92, 246, 0.05)); | |
| opacity: 0; | |
| transition: opacity 0.3s ease; | |
| } | |
| .upload-section:hover::before, | |
| .upload-section.drag-over::before { | |
| opacity: 1; | |
| } | |
| .upload-section:hover, | |
| .upload-section.drag-over { | |
| border-color: var(--primary); | |
| transform: scale(1.01); | |
| } | |
| .upload-icon { | |
| width: 64px; | |
| height: 64px; | |
| margin: 0 auto 1rem; | |
| background: linear-gradient(135deg, var(--gradient-1), var(--gradient-3)); | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| box-shadow: 0 8px 32px rgba(99, 102, 241, 0.3); | |
| } | |
| .upload-icon svg { | |
| width: 32px; | |
| height: 32px; | |
| color: white; | |
| } | |
| .upload-text { | |
| font-size: 1.1rem; | |
| margin-bottom: 0.5rem; | |
| } | |
| .upload-hint { | |
| color: var(--text-secondary); | |
| font-size: 0.9rem; | |
| } | |
| .file-types { | |
| display: flex; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| margin-top: 1rem; | |
| flex-wrap: wrap; | |
| } | |
| .file-type-badge { | |
| padding: 0.25rem 0.75rem; | |
| background: rgba(99, 102, 241, 0.15); | |
| border-radius: 12px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| color: var(--primary); | |
| text-transform: uppercase; | |
| } | |
| #fileInput { | |
| display: none; | |
| } | |
| /* File Info */ | |
| .file-info { | |
| display: none; | |
| margin-top: 1.5rem; | |
| padding: 1rem; | |
| background: rgba(99, 102, 241, 0.1); | |
| border-radius: 12px; | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| } | |
| .file-info.active { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| } | |
| .file-icon { | |
| width: 40px; | |
| height: 40px; | |
| background: var(--primary); | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| flex-shrink: 0; | |
| } | |
| .file-details { | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .file-name { | |
| font-weight: 600; | |
| margin-bottom: 0.25rem; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .file-size { | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| } | |
| .remove-file { | |
| width: 36px; | |
| height: 36px; | |
| background: rgba(239, 68, 68, 0.15); | |
| border: 1px solid rgba(239, 68, 68, 0.3); | |
| border-radius: 8px; | |
| color: var(--danger); | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.2s ease; | |
| flex-shrink: 0; | |
| } | |
| .remove-file:hover { | |
| background: rgba(239, 68, 68, 0.25); | |
| transform: scale(1.05); | |
| } | |
| /* Controls Section */ | |
| .controls-section { | |
| margin-top: 2rem; | |
| padding-top: 2rem; | |
| border-top: 1px solid var(--border); | |
| display: none; | |
| } | |
| .controls-section.active { | |
| display: block; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| @keyframes fadeIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .control-group { | |
| margin-bottom: 1.5rem; | |
| } | |
| .control-label { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 0.75rem; | |
| } | |
| .control-label span { | |
| font-weight: 500; | |
| } | |
| .control-value { | |
| font-size: 0.85rem; | |
| color: var(--primary); | |
| font-weight: 600; | |
| } | |
| /* Custom Range Slider */ | |
| input[type="range"] { | |
| width: 100%; | |
| height: 8px; | |
| -webkit-appearance: none; | |
| background: var(--bg-dark); | |
| border-radius: 4px; | |
| outline: none; | |
| } | |
| input[type="range"]::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2)); | |
| border-radius: 50%; | |
| cursor: pointer; | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4); | |
| transition: transform 0.2s ease; | |
| } | |
| input[type="range"]::-webkit-slider-thumb:hover { | |
| transform: scale(1.1); | |
| } | |
| input[type="range"]::-moz-range-thumb { | |
| width: 20px; | |
| height: 20px; | |
| background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2)); | |
| border-radius: 50%; | |
| cursor: pointer; | |
| border: none; | |
| } | |
| /* Buttons - Fixed Styles */ | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| padding: 0.875rem 1.5rem; | |
| border-radius: 12px; | |
| font-size: 0.95rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| border: none; | |
| text-decoration: none; | |
| white-space: nowrap; | |
| } | |
| .btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| transform: none ; | |
| box-shadow: none ; | |
| } | |
| .btn-primary { | |
| width: 100%; | |
| background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2)); | |
| color: white; | |
| box-shadow: 0 8px 24px rgba(99, 102, 241, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .btn-primary::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); | |
| transition: left 0.5s ease; | |
| } | |
| .btn-primary:hover:not(:disabled)::before { | |
| left: 100%; | |
| } | |
| .btn-primary:hover:not(:disabled) { | |
| transform: translateY(-2px); | |
| box-shadow: 0 12px 32px rgba(99, 102, 241, 0.4); | |
| } | |
| .btn-secondary { | |
| background: var(--bg-elevated); | |
| color: var(--text-primary); | |
| border: 1px solid var(--border); | |
| } | |
| .btn-secondary:hover:not(:disabled) { | |
| background: var(--bg-card-hover); | |
| border-color: var(--text-secondary); | |
| transform: translateY(-2px); | |
| } | |
| .btn-danger { | |
| background: rgba(239, 68, 68, 0.15); | |
| color: var(--danger); | |
| border: 1px solid rgba(239, 68, 68, 0.3); | |
| } | |
| .btn-danger:hover:not(:disabled) { | |
| background: rgba(239, 68, 68, 0.25); | |
| border-color: var(--danger); | |
| transform: translateY(-2px); | |
| } | |
| .btn-success { | |
| background: linear-gradient(135deg, var(--secondary), #059669); | |
| color: white; | |
| box-shadow: 0 8px 24px rgba(16, 185, 129, 0.3); | |
| } | |
| .btn-success:hover:not(:disabled) { | |
| transform: translateY(-2px); | |
| box-shadow: 0 12px 32px rgba(16, 185, 129, 0.4); | |
| } | |
| .btn-icon { | |
| padding: 0.75rem; | |
| } | |
| /* Progress Section */ | |
| .progress-section { | |
| display: none; | |
| margin-top: 2rem; | |
| } | |
| .progress-section.active { | |
| display: block; | |
| } | |
| .progress-container { | |
| background: var(--bg-dark); | |
| border-radius: 12px; | |
| padding: 1.5rem; | |
| text-align: center; | |
| } | |
| .progress-text { | |
| margin-bottom: 1rem; | |
| font-weight: 500; | |
| } | |
| .progress-bar { | |
| width: 100%; | |
| height: 8px; | |
| background: var(--bg-card-hover); | |
| border-radius: 4px; | |
| overflow: hidden; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, var(--gradient-1), var(--gradient-2), var(--gradient-3)); | |
| border-radius: 4px; | |
| transition: width 0.3s ease; | |
| position: relative; | |
| } | |
| .progress-fill::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); | |
| animation: shimmer 1.5s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { | |
| transform: translateX(-100%); | |
| } | |
| 100% { | |
| transform: translateX(100%); | |
| } | |
| } | |
| .progress-steps { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-top: 1rem; | |
| font-size: 0.8rem; | |
| color: var(--text-secondary); | |
| } | |
| .progress-step { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| opacity: 0.5; | |
| transition: opacity 0.3s ease; | |
| } | |
| .progress-step.active { | |
| opacity: 1; | |
| color: var(--primary); | |
| } | |
| .progress-step.completed { | |
| opacity: 1; | |
| color: var(--secondary); | |
| } | |
| .progress-step svg { | |
| display: none; | |
| } | |
| .progress-step.completed svg { | |
| display: inline-block; | |
| } | |
| .progress-step .step-text { | |
| display: inline; | |
| } | |
| .progress-step.completed .step-text { | |
| display: none; | |
| } | |
| /* Results Section */ | |
| .results-section { | |
| display: none; | |
| margin-top: 2rem; | |
| } | |
| .results-section.active { | |
| display: block; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| .result-card { | |
| background: var(--bg-dark); | |
| border-radius: 16px; | |
| padding: 1.5rem; | |
| margin-bottom: 1rem; | |
| } | |
| .result-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| margin-bottom: 1.5rem; | |
| } | |
| .result-icon { | |
| width: 48px; | |
| height: 48px; | |
| background: linear-gradient(135deg, var(--secondary), #059669); | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| flex-shrink: 0; | |
| } | |
| .result-icon svg { | |
| width: 24px; | |
| height: 24px; | |
| color: white; | |
| } | |
| .result-title { | |
| font-size: 1.25rem; | |
| font-weight: 600; | |
| } | |
| .result-subtitle { | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| } | |
| /* Audio Player */ | |
| .audio-player { | |
| background: var(--bg-card); | |
| border-radius: 12px; | |
| padding: 1rem; | |
| margin-bottom: 1rem; | |
| } | |
| .audio-player:last-of-type { | |
| margin-bottom: 1.5rem; | |
| } | |
| .audio-info { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| } | |
| .audio-label { | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| font-weight: 500; | |
| } | |
| .audio-label.processed { | |
| color: var(--secondary); | |
| } | |
| .audio-time { | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .waveform-container { | |
| height: 60px; | |
| background: var(--bg-dark); | |
| border-radius: 8px; | |
| margin-bottom: 1rem; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .waveform-canvas { | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .audio-controls { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| } | |
| .play-btn { | |
| width: 44px; | |
| height: 44px; | |
| min-width: 44px; | |
| background: var(--primary); | |
| border: none; | |
| border-radius: 50%; | |
| color: white; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.2s ease; | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); | |
| } | |
| .play-btn:hover { | |
| transform: scale(1.05); | |
| background: var(--primary-hover); | |
| } | |
| .play-btn.playing { | |
| animation: pulse 1s infinite; | |
| } | |
| .play-btn.processed { | |
| background: var(--secondary); | |
| box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); | |
| } | |
| .play-btn.processed:hover { | |
| background: var(--secondary-hover); | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); | |
| } | |
| 50% { | |
| box-shadow: 0 4px 20px rgba(99, 102, 241, 0.5); | |
| } | |
| } | |
| .play-btn svg { | |
| width: 18px; | |
| height: 18px; | |
| } | |
| .audio-slider { | |
| flex: 1; | |
| } | |
| .audio-slider input[type="range"] { | |
| height: 4px; | |
| } | |
| .audio-slider input[type="range"]::-webkit-slider-thumb { | |
| width: 14px; | |
| height: 14px; | |
| } | |
| /* Action Buttons Container */ | |
| .action-buttons { | |
| display: flex; | |
| gap: 1rem; | |
| flex-wrap: wrap; | |
| } | |
| .action-buttons .btn { | |
| flex: 1; | |
| min-width: 140px; | |
| } | |
| .action-buttons .btn svg { | |
| width: 18px; | |
| height: 18px; | |
| } | |
| /* Comparison Toggle */ | |
| .comparison-toggle { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| margin-bottom: 1.5rem; | |
| cursor: pointer; | |
| padding: 0.75rem 1rem; | |
| background: var(--bg-dark); | |
| border-radius: 10px; | |
| transition: background 0.2s ease; | |
| } | |
| .comparison-toggle:hover { | |
| background: var(--bg-elevated); | |
| } | |
| .toggle-switch { | |
| width: 44px; | |
| height: 24px; | |
| background: var(--bg-card-hover); | |
| border-radius: 12px; | |
| position: relative; | |
| transition: background 0.3s ease; | |
| flex-shrink: 0; | |
| } | |
| .toggle-switch::after { | |
| content: ''; | |
| position: absolute; | |
| width: 18px; | |
| height: 18px; | |
| background: white; | |
| border-radius: 50%; | |
| top: 3px; | |
| left: 3px; | |
| transition: transform 0.3s ease; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.2); | |
| } | |
| .comparison-toggle.active .toggle-switch { | |
| background: var(--primary); | |
| } | |
| .comparison-toggle.active .toggle-switch::after { | |
| transform: translateX(20px); | |
| } | |
| .comparison-toggle span:last-child { | |
| font-size: 0.9rem; | |
| color: var(--text-secondary); | |
| } | |
| /* Toast Notification */ | |
| .toast { | |
| position: fixed; | |
| bottom: 2rem; | |
| right: 2rem; | |
| background: var(--bg-card); | |
| border: 1px solid var(--border); | |
| border-radius: 12px; | |
| padding: 1rem 1.5rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4); | |
| transform: translateY(100px); | |
| opacity: 0; | |
| transition: all 0.3s ease; | |
| z-index: 1000; | |
| max-width: calc(100vw - 4rem); | |
| } | |
| .toast.show { | |
| transform: translateY(0); | |
| opacity: 1; | |
| } | |
| .toast.error { | |
| border-color: var(--danger); | |
| background: rgba(239, 68, 68, 0.1); | |
| } | |
| .toast.success { | |
| border-color: var(--secondary); | |
| background: rgba(16, 185, 129, 0.1); | |
| } | |
| .toast-icon { | |
| width: 20px; | |
| height: 20px; | |
| flex-shrink: 0; | |
| } | |
| .toast.error .toast-icon { | |
| color: var(--danger); | |
| } | |
| .toast.success .toast-icon { | |
| color: var(--secondary); | |
| } | |
| /* Responsive */ | |
| @media (max-width: 640px) { | |
| h1 { | |
| font-size: 1.75rem; | |
| } | |
| .main-card { | |
| padding: 1.5rem; | |
| } | |
| .upload-section { | |
| padding: 2rem 1rem; | |
| } | |
| .file-info.active { | |
| flex-wrap: wrap; | |
| } | |
| .file-details { | |
| order: 2; | |
| width: 100%; | |
| margin-top: 0.5rem; | |
| } | |
| .remove-file { | |
| order: 3; | |
| margin-left: auto; | |
| } | |
| .action-buttons { | |
| flex-direction: column; | |
| } | |
| .action-buttons .btn { | |
| width: 100%; | |
| } | |
| .audio-controls { | |
| gap: 0.75rem; | |
| } | |
| .play-btn { | |
| width: 40px; | |
| height: 40px; | |
| min-width: 40px; | |
| } | |
| .toast { | |
| left: 1rem; | |
| right: 1rem; | |
| bottom: 1rem; | |
| } | |
| .progress-steps { | |
| flex-wrap: wrap; | |
| gap: 0.5rem; | |
| justify-content: center; | |
| } | |
| } | |
| /* Loading Spinner for Button */ | |
| .btn-loading { | |
| position: relative; | |
| color: transparent ; | |
| } | |
| .btn-loading::after { | |
| content: ''; | |
| position: absolute; | |
| width: 20px; | |
| height: 20px; | |
| border: 2px solid rgba(255,255,255,0.3); | |
| border-top-color: white; | |
| border-radius: 50%; | |
| animation: spin 0.8s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bg-pattern"></div> | |
| <div class="container"> | |
| <header> | |
| <div class="logo"> | |
| <div class="logo-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" | |
| stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 012.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75z" /> | |
| </svg> | |
| </div> | |
| <h1>Noise Reducer</h1> | |
| </div> | |
| <p class="subtitle">Remove crowd noise from your audio & video files</p> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with"> | |
| Built with anycoder | |
| </a> | |
| </header> | |
| <main class="main-card"> | |
| <!-- Upload Section --> | |
| <div class="upload-section" id="uploadSection"> | |
| <div class="upload-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" | |
| stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" /> | |
| </svg> | |
| </div> | |
| <p class="upload-text">Drop your file here or click to browse</p> | |
| <p class="upload-hint">Maximum file size: 100MB</p> | |
| <div class="file-types"> | |
| <span class="file-type-badge">MP3</span> | |
| <span class="file-type-badge">MP4</span> | |
| <span class="file-type-badge">WAV</span> | |
| <span class="file-type-badge">M4A</span> | |
| </div> | |
| <input type="file" id="fileInput" accept=".mp3,.mp4,.wav,.m4a,audio/*,video/*"> | |
| </div> | |
| <!-- File Info --> | |
| <div class="file-info" id="fileInfo"> | |
| <div class="file-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24" | |
| stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3" /> | |
| </svg> | |
| </div> | |
| <div class="file-details"> | |
| <div class="file-name" id="fileName">filename.mp3</div> | |
| <div class="file-size" id="fileSize">0 MB</div> | |
| </div> | |
| <button class="remove-file" id="removeFile" title="Remove file"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <!-- Controls Section --> | |
| <div class="controls-section" id="controlsSection"> | |
| <div class="control-group"> | |
| <div class="control-label"> | |
| <span>Noise Reduction Level</span> | |
| <span class="control-value" id="noiseLevelValue">50%</span> | |
| </div> | |
| <input type="range" id="noiseLevel" min="0" max="100" value="50"> | |
| </div> | |
| <div class="control-group"> | |
| <div class="control-label"> | |
| <span>Sensitivity</span> | |
| <span class="control-value" id="sensitivityValue">Medium</span> | |
| </div> | |
| <input type="range" id="sensitivity" min="0" max="100" value="50"> | |
| </div> | |
| <div class="comparison-toggle" id="comparisonToggle"> | |
| <div class="toggle-switch"></div> | |
| <span>Preview original audio</span> | |
| </div> | |
| <button class="btn btn-primary" id="processBtn"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /> | |
| </svg> | |
| Remove Noise | |
| </button> | |
| </div> | |
| <!-- Progress Section --> | |
| <div class="progress-section" id="progressSection"> | |
| <div class="progress-container"> | |
| <p class="progress-text" id="progressText">Processing your audio...</p> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" id="progressFill" style="width: 0%"></div> | |
| </div> | |
| <div class="progress-steps"> | |
| <div class="progress-step" id="step1"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> | |
| </svg> | |
| <span class="step-text">Analyzing</span> | |
| </div> | |
| <div class="progress-step" id="step2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> | |
| </svg> | |
| <span class="step-text">Reducing</span> | |
| </div> | |
| <div class="progress-step" id="step3"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> | |
| </svg> | |
| <span class="step-text">Finalizing</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Results Section --> | |
| <div class="results-section" id="resultsSection"> | |
| <div class="result-card"> | |
| <div class="result-header"> | |
| <div class="result-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" | |
| stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" /> | |
| </svg> | |
| </div> | |
| <div> | |
| <div class="result-title">Processing Complete!</div> | |
| <div class="result-subtitle">Your audio has been cleaned</div> | |
| </div> | |
| </div> | |
| <!-- Original Audio Player --> | |
| <div class="audio-player" id="originalPlayer"> | |
| <div class="audio-info"> | |
| <span class="audio-label">Original Audio</span> | |
| <span class="audio-time" id="originalTime">0:00 / 0:00</span> | |
| </div> | |
| <div class="waveform-container"> | |
| <canvas class="waveform-canvas" id="originalWaveform"></canvas> | |
| </div> | |
| <div class="audio-controls"> | |
| <button class="play-btn" id="playOriginal" title="Play original"> | |
| <svg class="play-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 24 24"> | |
| <path d="M8 5v14l11-7z"/> | |
| </svg> | |
| <svg class="pause-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 24 24" style="display:none"> | |
| <path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/> | |
| </svg> | |
| </button> | |
| <div class="audio-slider"> | |
| <input type="range" id="originalSeek" min="0" max="100" value="0"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Processed Audio Player --> | |
| <div class="audio-player" id="processedPlayer"> | |
| <div class="audio-info"> | |
| <span class="audio-label processed">Processed Audio</span> | |
| <span class="audio-time" id="processedTime">0:00 / 0:00</span> | |
| </div> | |
| <div class="waveform-container"> | |
| <canvas class="waveform-canvas" id="processedWaveform"></canvas> | |
| </div> | |
| <div class="audio-controls"> | |
| <button class="play-btn processed" id="playProcessed" title="Play processed"> | |
| <svg class="play-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 24 24"> | |
| <path d="M8 5v14l11-7z"/> | |
| </svg> | |
| <svg class="pause-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 24 24" style="display:none"> | |
| <path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/> | |
| </svg> | |
| </button> | |
| <div class="audio-slider"> | |
| <input type="range" id="processedSeek" min="0" max="100" value="0"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Action Buttons --> | |
| <div class="action-buttons"> | |
| <button class="btn btn-secondary" id="resetBtn"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /> | |
| </svg> | |
| Start Over | |
| </button> | |
| <button class="btn btn-success" id="downloadBtn"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /> | |
| </svg> | |
| Download | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Toast Notification --> | |
| <div class="toast" id="toast"> | |
| <svg class="toast-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| <span id="toastMessage">Message</span> | |
| </div> | |
| <script> | |
| // Application State | |
| const state = { | |
| file: null, | |
| originalAudioBuffer: null, | |
| processedAudioBuffer: null, | |
| originalAudio: null, | |
| processedAudio: null, | |
| isPlayingOriginal: false, | |
| isPlayingProcessed: false, | |
| previewOriginal: false, | |
| audioContext: null, | |
| sourceNodes: { | |
| original: null, | |
| processed: null | |
| }, | |
| gainNodes: { | |
| original: null, | |
| processed: null | |
| }, | |
| analyserNodes: { | |
| original: null, | |
| processed: null | |
| }, | |
| startTime: 0, | |
| pauseTime: 0 | |
| }; | |
| // DOM Elements | |
| const elements = { | |
| uploadSection: document.getElementById('uploadSection'), | |
| fileInput: document.getElementById('fileInput'), | |
| fileInfo: document.getElementById('fileInfo'), | |
| fileName: document.getElementById('fileName'), | |
| fileSize: document.getElementById('fileSize'), | |
| removeFile: document.getElementById('removeFile'), | |
| controlsSection: document.getElementById('controlsSection'), | |
| noiseLevel: document.getElementById('noiseLevel'), | |
| noiseLevelValue: document.getElementById('noiseLevelValue'), | |
| sensitivity: document.getElementById('sensitivity'), | |
| sensitivityValue: document.getElementById('sensitivityValue'), | |
| comparisonToggle: document.getElementById('comparisonToggle'), | |
| processBtn: document.getElementById('processBtn'), | |
| progressSection: document.getElementById('progressSection'), | |
| progressText: document.getElementById('progressText'), | |
| progressFill: document.getElementById('progressFill'), | |
| step1: document.getElementById('step1'), | |
| step2: document.getElementById('step2'), | |
| step3: document.getElementById('step3'), | |
| resultsSection: document.getElementById('resultsSection'), | |
| playOriginal: document.getElementById('playOriginal'), | |
| playProcessed: document.getElementById('playProcessed'), | |
| originalSeek: document.getElementById('originalSeek'), | |
| processedSeek: document.getElementById('processedSeek'), | |
| originalTime: document.getElementById('originalTime'), | |
| processedTime: document.getElementById('processedTime'), | |
| originalWaveform: document.getElementById('originalWaveform'), | |
| processedWaveform: document.getElementById('processedWaveform'), | |
| resetBtn: document.getElementById('resetBtn'), | |
| downloadBtn: document.getElementById('downloadBtn'), | |
| toast: document.getElementById('toast'), | |
| toastMessage: document.getElementById('toastMessage') | |
| }; | |
| // Initialize Audio Context | |
| function initAudioContext() { | |
| if (!state.audioContext) { | |
| state.audioContext = new (window.AudioContext || window.webkitAudioContext)(); | |
| } | |
| } | |
| // File Upload Handling | |
| elements.uploadSection.addEventListener('click', () => elements.fileInput.click()); | |
| elements.uploadSection.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| elements.uploadSection.classList.add('drag-over'); | |
| }); | |
| elements.uploadSection.addEventListener('dragleave', () => { | |
| elements.uploadSection.classList.remove('drag-over'); | |
| }); | |
| elements.uploadSection.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| elements.uploadSection.classList.remove('drag-over'); | |
| const file = e.dataTransfer.files[0]; | |
| if (file) handleFileSelect(file); | |
| }); | |
| elements.fileInput |