izaheeerr commited on
Commit
685732c
·
verified ·
1 Parent(s): 6aa4fbf

Initial Push

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ media/audio/sample-song.mp3 filter=lfs diff=lfs merge=lfs -text
core/__init__.py ADDED
File without changes
core/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (152 Bytes). View file
 
core/__pycache__/settings.cpython-312.pyc ADDED
Binary file (2.87 kB). View file
 
core/__pycache__/urls.cpython-312.pyc ADDED
Binary file (720 Bytes). View file
 
core/__pycache__/wsgi.cpython-312.pyc ADDED
Binary file (633 Bytes). View file
 
core/asgi.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ASGI config for core project.
3
+
4
+ It exposes the ASGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.asgi import get_asgi_application
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
15
+
16
+ application = get_asgi_application()
core/settings.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Django settings for core project.
3
+
4
+ Generated by 'django-admin startproject' using Django 6.0.4.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/6.0/topics/settings/
8
+
9
+ For the full list of settings and their values, see
10
+ https://docs.djangoproject.com/en/6.0/ref/settings/
11
+ """
12
+
13
+ from pathlib import Path
14
+ import os
15
+ # Build paths inside the project like this: BASE_DIR / 'subdir'.
16
+ BASE_DIR = Path(__file__).resolve().parent.parent
17
+
18
+
19
+ # Quick-start development settings - unsuitable for production
20
+ # See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/
21
+
22
+ # SECURITY WARNING: keep the secret key used in production secret!
23
+ SECRET_KEY = 'django-insecure-bpm=z9@@=29etqf8x)a_8_-a^9adja%!@bt)%0*!*$hewld4*t'
24
+
25
+ # SECURITY WARNING: don't run with debug turned on in production!
26
+ DEBUG = True
27
+
28
+ ALLOWED_HOSTS = []
29
+
30
+
31
+ # Application definition
32
+
33
+ INSTALLED_APPS = [
34
+ 'django.contrib.admin',
35
+ 'django.contrib.auth',
36
+ 'django.contrib.contenttypes',
37
+ 'django.contrib.sessions',
38
+ 'django.contrib.messages',
39
+ 'django.contrib.staticfiles',
40
+ 'transcriber'
41
+ ]
42
+
43
+ MIDDLEWARE = [
44
+ 'django.middleware.security.SecurityMiddleware',
45
+ 'django.contrib.sessions.middleware.SessionMiddleware',
46
+ 'django.middleware.common.CommonMiddleware',
47
+ 'django.middleware.csrf.CsrfViewMiddleware',
48
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
49
+ 'django.contrib.messages.middleware.MessageMiddleware',
50
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51
+ ]
52
+
53
+ ROOT_URLCONF = 'core.urls'
54
+
55
+ TEMPLATES = [
56
+ {
57
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')],
59
+ 'APP_DIRS': True,
60
+ 'OPTIONS': {
61
+ 'context_processors': [
62
+ 'django.template.context_processors.request',
63
+ 'django.contrib.auth.context_processors.auth',
64
+ 'django.contrib.messages.context_processors.messages',
65
+ ],
66
+ },
67
+ },
68
+ ]
69
+
70
+ WSGI_APPLICATION = 'core.wsgi.application'
71
+
72
+
73
+ # Database
74
+ # https://docs.djangoproject.com/en/6.0/ref/settings/#databases
75
+
76
+ DATABASES = {
77
+ 'default': {
78
+ 'ENGINE': 'django.db.backends.sqlite3',
79
+ 'NAME': BASE_DIR / 'db.sqlite3',
80
+ }
81
+ }
82
+
83
+
84
+ # Password validation
85
+ # https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators
86
+
87
+ AUTH_PASSWORD_VALIDATORS = [
88
+ {
89
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
90
+ },
91
+ {
92
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
93
+ },
94
+ {
95
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
96
+ },
97
+ {
98
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
99
+ },
100
+ ]
101
+
102
+
103
+ # Internationalization
104
+ # https://docs.djangoproject.com/en/6.0/topics/i18n/
105
+
106
+ LANGUAGE_CODE = 'en-us'
107
+
108
+ TIME_ZONE = 'UTC'
109
+
110
+ USE_I18N = True
111
+
112
+ USE_TZ = True
113
+
114
+
115
+ # Static files (CSS, JavaScript, Images)
116
+ # https://docs.djangoproject.com/en/6.0/howto/static-files/
117
+
118
+
119
+
120
+ STATIC_URL = 'static/'
121
+ STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
122
+ STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
123
+
124
+ # URL that handles the media served from MEDIA_ROOT
125
+ MEDIA_URL = '/media/'
126
+
127
+ # Absolute filesystem path to the directory that will hold user-uploaded files
128
+ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
core/urls.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.contrib import admin
2
+ from django.urls import path, include
3
+ from django.conf import settings
4
+ # Update this specific line below:
5
+ from django.conf.urls.static import static
6
+
7
+ urlpatterns = [
8
+ path('admin/', admin.site.urls), # Note: corrected to .urls
9
+ path('', include('transcriber.urls')),
10
+ ]
11
+
12
+ # This allows Django to serve files from the media folder during development
13
+ if settings.DEBUG:
14
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
core/wsgi.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ WSGI config for core project.
3
+
4
+ It exposes the WSGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.wsgi import get_wsgi_application
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
15
+
16
+ application = get_wsgi_application()
manage.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Django's command-line utility for administrative tasks."""
3
+ import os
4
+ import sys
5
+
6
+
7
+ def main():
8
+ """Run administrative tasks."""
9
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
10
+ try:
11
+ from django.core.management import execute_from_command_line
12
+ except ImportError as exc:
13
+ raise ImportError(
14
+ "Couldn't import Django. Are you sure it's installed and "
15
+ "available on your PYTHONPATH environment variable? Did you "
16
+ "forget to activate a virtual environment?"
17
+ ) from exc
18
+ execute_from_command_line(sys.argv)
19
+
20
+
21
+ if __name__ == '__main__':
22
+ main()
media/audio/sample-song.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8b20c34a22298d81eac0181f8956c60ea7b23a39782d161884e272fcc3713bbd
3
+ size 360533
transcriber/__init__.py ADDED
File without changes
transcriber/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (159 Bytes). View file
 
transcriber/__pycache__/admin.cpython-312.pyc ADDED
Binary file (343 Bytes). View file
 
transcriber/__pycache__/apps.cpython-312.pyc ADDED
Binary file (414 Bytes). View file
 
transcriber/__pycache__/models.cpython-312.pyc ADDED
Binary file (708 Bytes). View file
 
transcriber/__pycache__/urls.cpython-312.pyc ADDED
Binary file (363 Bytes). View file
 
transcriber/__pycache__/views.cpython-312.pyc ADDED
Binary file (1.47 kB). View file
 
transcriber/admin.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from django.contrib import admin
2
+ from .models import Transcription
3
+
4
+ # Register your models here.
5
+ admin.site.register(Transcription)
transcriber/apps.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class TranscriberConfig(AppConfig):
5
+ name = 'transcriber'
transcriber/migrations/0001_initial.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 6.0.4 on 2026-05-05 11:45
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ initial = True
9
+
10
+ dependencies = [
11
+ ]
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name='Transcription',
16
+ fields=[
17
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18
+ ('audio_file', models.FileField(upload_to='audio/')),
19
+ ('transcript_text', models.TextField(blank=True)),
20
+ ('created_at', models.DateTimeField(auto_now_add=True)),
21
+ ],
22
+ ),
23
+ ]
transcriber/migrations/__init__.py ADDED
File without changes
transcriber/migrations/__pycache__/0001_initial.cpython-312.pyc ADDED
Binary file (1.09 kB). View file
 
transcriber/migrations/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (170 Bytes). View file
 
transcriber/models.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from django.db import models
2
+
3
+
4
+ class Transcription(models.Model):
5
+ audio_file = models.FileField(upload_to='audio/')
6
+ transcript_text = models.TextField(blank=True)
7
+ created_at = models.DateTimeField(auto_now_add=True)
transcriber/templates/result.html ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Transcription Result</title>
6
+ <script src="https://cdn.tailwindcss.com"></script>
7
+ </head>
8
+ <body class="bg-gradient-to-br from-gray-900 to-black min-h-screen p-10 text-white">
9
+
10
+ <div class="max-w-4xl mx-auto">
11
+ <div class="flex justify-between items-center mb-8">
12
+ <h2 class="text-2xl font-bold text-purple-400">Transcription Complete</h2>
13
+ <a href="/" class="text-sm text-gray-400 hover:text-white transition">← Upload another</a>
14
+ </div>
15
+
16
+ <div class="bg-white/5 border border-white/10 rounded-2xl p-8 shadow-xl">
17
+ <h3 class="text-xs font-semibold text-gray-500 uppercase tracking-widest mb-4">Output Text</h3>
18
+ <p class="text-lg leading-relaxed text-gray-200">
19
+ {{ transcription.transcript_text }}
20
+ </p>
21
+ </div>
22
+
23
+ <div class="mt-6 flex gap-4">
24
+ <button onclick="navigator.clipboard.writeText('{{ transcription.transcript_text|escapejs }}')" class="px-6 py-2 bg-white/10 hover:bg-white/20 rounded-lg text-sm transition">
25
+ Copy to Clipboard
26
+ </button>
27
+ </div>
28
+ </div>
29
+
30
+ </body>
31
+ </html>
transcriber/templates/upload.html ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Audio Transcriber</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ </head>
9
+ <body class="bg-gradient-to-br from-indigo-900 via-purple-900 to-black min-h-screen flex items-center justify-center p-6">
10
+
11
+ <div class="max-w-md w-full bg-white/10 backdrop-blur-lg rounded-3xl p-8 shadow-2xl border border-white/20">
12
+ <h1 class="text-3xl font-bold text-white mb-2 text-center">Audio to Text</h1>
13
+ <p class="text-purple-200 text-center mb-8 text-sm">Upload your MP3 or WAV and let AI do the rest.</p>
14
+
15
+ <form method="POST" enctype="multipart/form-data" class="space-y-6">
16
+ {% csrf_token %}
17
+
18
+ <!-- Upload Area -->
19
+ <div class="relative group">
20
+ <label id="drop-zone" class="flex flex-col items-center justify-center w-full h-48 border-2 border-dashed border-purple-400/50 rounded-2xl cursor-pointer hover:bg-white/5 hover:border-purple-300 transition-all">
21
+ <div class="flex flex-col items-center justify-center pt-5 pb-6">
22
+ <svg id="upload-icon" class="w-12 h-12 mb-3 text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
23
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
24
+ </svg>
25
+ <p id="file-name" class="text-sm text-gray-300 px-4 text-center">Click to upload or drag and drop</p>
26
+ </div>
27
+ <input type="file" id="audio-input" name="audio" class="hidden" accept="audio/*" required />
28
+ </label>
29
+ </div>
30
+
31
+ <!-- Audio Preview Player (Hidden by default) -->
32
+ <div id="preview-container" class="hidden animate-fade-in">
33
+ <p class="text-xs text-purple-300 mb-2 font-semibold uppercase tracking-wider">File Preview:</p>
34
+ <audio id="audio-preview" controls class="w-full h-10 rounded-lg bg-white/5"></audio>
35
+ </div>
36
+
37
+ <button type="submit" class="w-full py-4 bg-gradient-to-r from-purple-500 to-indigo-600 text-white font-bold rounded-xl shadow-lg hover:from-purple-600 hover:to-indigo-700 transform hover:-translate-y-1 transition-all">
38
+ Start Transcription
39
+ </button>
40
+ </form>
41
+ </div>
42
+
43
+ <script>
44
+ // Add this to your existing script
45
+ const form = document.querySelector('form');
46
+ const button = document.querySelector('button[type="submit"]');
47
+
48
+ form.addEventListener('submit', function() {
49
+ button.disabled = true;
50
+ button.innerHTML = `
51
+ <svg class="animate-spin h-5 w-5 mr-3 inline-block border-2 border-t-transparent border-white rounded-full" viewBox="0 0 24 24"></svg>
52
+ Processing Audio...
53
+ `;
54
+ button.classList.add('opacity-75', 'cursor-not-allowed');
55
+ });
56
+ const audioInput = document.getElementById('audio-input');
57
+ const fileName = document.getElementById('file-name');
58
+ const previewContainer = document.getElementById('preview-container');
59
+ const audioPreview = document.getElementById('audio-preview');
60
+ const dropZone = document.getElementById('drop-zone');
61
+
62
+ audioInput.addEventListener('change', function() {
63
+ const file = this.files[0];
64
+ if (file) {
65
+ // Update text to show file name
66
+ fileName.textContent = `Selected: ${file.name}`;
67
+ fileName.classList.remove('text-gray-300');
68
+ fileName.classList.add('text-green-400', 'font-medium');
69
+
70
+ // Show and load the audio preview
71
+ const url = URL.createObjectURL(file);
72
+ audioPreview.src = url;
73
+ previewContainer.classList.remove('hidden');
74
+
75
+ // Change border color to show success
76
+ dropZone.classList.remove('border-purple-400/50');
77
+ dropZone.classList.add('border-green-500/50');
78
+ }
79
+ });
80
+ </script>
81
+
82
+ <style>
83
+ .animate-fade-in {
84
+ animation: fadeIn 0.5s ease-in-out;
85
+ }
86
+ @keyframes fadeIn {
87
+ from { opacity: 0; transform: translateY(10px); }
88
+ to { opacity: 1; transform: translateY(0); }
89
+ }
90
+ /* Custom styling for the audio player to match the theme */
91
+ audio::-webkit-media-controls-panel {
92
+ background-color: rgba(255, 255, 255, 0.1);
93
+ }
94
+ </style>
95
+ </body>
96
+ </html>
transcriber/tests.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
transcriber/urls.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from django.urls import path
2
+ from . import views
3
+
4
+ urlpatterns = [
5
+ path('', views.transcribe_audio, name='upload_audio'),
6
+ ]
transcriber/views.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.shortcuts import render
2
+ from .models import Transcription
3
+ from faster_whisper import WhisperModel
4
+ import os
5
+
6
+ # Load model ONCE globally (outside the view) to save time
7
+ # 'int8' quantization makes it much faster on CPU
8
+ model = WhisperModel("base", device="cpu", compute_type="int8")
9
+
10
+ def transcribe_audio(request):
11
+ if request.method == 'POST' and request.FILES.get('audio'):
12
+ audio_obj = Transcription.objects.create(audio_file=request.FILES['audio'])
13
+
14
+ # transcribe returns a generator of segments
15
+ segments, info = model.transcribe(audio_obj.audio_file.path, beam_size=5)
16
+
17
+ # Combine all segments into one full string
18
+ full_text = "".join([segment.text for segment in segments])
19
+
20
+ audio_obj.transcript_text = full_text.strip()
21
+ audio_obj.save()
22
+
23
+ return render(request, 'result.html', {'transcription': audio_obj})
24
+
25
+ return render(request, 'upload.html')