Minor update
- added transcription folder with checker and transcription modules - logger is a separated module now
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
# Notecast
|
||||
|
||||
**Notecast** is a simple and minimalistic utilite to transcribe audiofiles to text and create a conspect.
|
||||
|
||||
Requires nvcc v12.8
|
||||
|
||||
You can create environment running
|
||||
```
|
||||
conda env create -f environment.yml
|
||||
```
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
name: notecast
|
||||
channels:
|
||||
- conda-forge
|
||||
- defaults
|
||||
- nvidia
|
||||
- pytorch
|
||||
dependencies:
|
||||
- accelerate=1.10.1=pyhcf101f3_0
|
||||
- aiohappyeyeballs=2.6.1=pyhd8ed1ab_0
|
||||
- aiohttp=3.12.15=pyh7db6752_0
|
||||
- aiosignal=1.4.0=pyhd8ed1ab_0
|
||||
- aom=3.6.0=hd77b12b_0
|
||||
- arrow-cpp=19.0.0=h82e8c66_4
|
||||
- async-timeout=5.0.1=pyhd8ed1ab_1
|
||||
- attrs=25.3.0=pyh71513ae_0
|
||||
- aws-c-auth=0.9.0=hd490b63_15
|
||||
- aws-c-cal=0.9.2=hd8a8e38_0
|
||||
- aws-c-common=0.12.3=h2466b09_0
|
||||
- aws-c-compression=0.3.1=h5d0e663_5
|
||||
- aws-c-event-stream=0.5.5=ha416645_0
|
||||
- aws-c-http=0.10.2=h81282ae_2
|
||||
- aws-c-io=0.20.1=hf7624bd_1
|
||||
- aws-c-mqtt=0.13.1=h5c1ae27_3
|
||||
- aws-c-s3=0.8.3=h1e843c7_0
|
||||
- aws-c-sdkutils=0.2.4=h5d0e663_0
|
||||
- aws-checksums=0.2.7=h5d0e663_1
|
||||
- aws-crt-cpp=0.32.10=h8abd1a4_2
|
||||
- aws-sdk-cpp=1.11.528=hd293286_1
|
||||
- blas=1.0=mkl
|
||||
- bottleneck=1.4.2=py312h4b0e54e_0
|
||||
- brotlicffi=1.0.9.2=py312h5da7b33_1
|
||||
- bzip2=1.0.8=h2bbff1b_6
|
||||
- c-ares=1.34.5=h2466b09_0
|
||||
- ca-certificates=2025.8.3=h4c7d964_0
|
||||
- cairo=1.18.4=he9e932c_0
|
||||
- certifi=2025.8.3=py312haa95532_0
|
||||
- cffi=1.17.1=py312h827c3e9_1
|
||||
- charset-normalizer=3.3.2=pyhd3eb1b0_0
|
||||
- colorama=0.4.6=pyhd8ed1ab_1
|
||||
- cuda-cccl=13.0.50=h23517cc_1
|
||||
- cuda-cccl_win-64=13.0.50=hc667259_1
|
||||
- cuda-cudart=12.4.127=0
|
||||
- cuda-cudart-dev=12.4.127=0
|
||||
- cuda-cupti=12.4.127=0
|
||||
- cuda-libraries=12.4.1=0
|
||||
- cuda-libraries-dev=12.4.1=0
|
||||
- cuda-nvrtc=12.4.127=0
|
||||
- cuda-nvrtc-dev=12.4.127=0
|
||||
- cuda-nvtx=12.4.127=0
|
||||
- cuda-opencl=13.0.39=0
|
||||
- cuda-opencl-dev=13.0.39=0
|
||||
- cuda-profiler-api=13.0.39=0
|
||||
- cuda-runtime=12.4.1=0
|
||||
- cuda-version=13.0=3
|
||||
- datasets=4.0.0=pyhcf101f3_0
|
||||
- dav1d=1.2.1=h2bbff1b_0
|
||||
- dill=0.3.8=pyhd8ed1ab_0
|
||||
- expat=2.7.1=h8ddb27b_0
|
||||
- ffmpeg=4.3.1=ha925a31_0
|
||||
- filelock=3.17.0=py312haa95532_0
|
||||
- fontconfig=2.14.1=hb33846d_3
|
||||
- freeglut=3.4.0=h8a1e904_1
|
||||
- freetype=2.13.3=h0620614_0
|
||||
- fribidi=1.0.10=h62dcd97_0
|
||||
- frozenlist=1.7.0=pyhf298e5d_0
|
||||
- fsspec=2025.3.0=pyhd8ed1ab_0
|
||||
- gflags=2.2.2=he0c23c2_1005
|
||||
- giflib=5.2.2=h7edc060_0
|
||||
- glog=0.5.0=h4797de2_0
|
||||
- gmp=6.3.0=h537511b_0
|
||||
- gmpy2=2.2.1=py312h827c3e9_0
|
||||
- graphite2=1.3.14=hd77b12b_1
|
||||
- harfbuzz=10.2.0=he2f9f60_1
|
||||
- hf-xet=1.1.8=py312h79d111c_0
|
||||
- huggingface_hub=0.34.4=pyhd8ed1ab_1
|
||||
- icu=73.1=h6c2663c_0
|
||||
- idna=3.7=py312haa95532_0
|
||||
- intel-openmp=2023.1.0=h59b6b97_46320
|
||||
- jinja2=3.1.6=py312haa95532_0
|
||||
- jpeg=9e=h827c3e9_3
|
||||
- khronos-opencl-icd-loader=2024.05.08=h8cc25b3_0
|
||||
- lcms2=2.16=h62be587_1
|
||||
- lerc=4.0.0=h5da7b33_0
|
||||
- libabseil=20250127.0=cxx17_h4eb7d71_0
|
||||
- libavif=1.1.1=h827c3e9_0
|
||||
- libbrotlicommon=1.0.9=hcfcfb64_9
|
||||
- libbrotlidec=1.0.9=hcfcfb64_9
|
||||
- libbrotlienc=1.0.9=hcfcfb64_9
|
||||
- libcublas=12.4.5.8=0
|
||||
- libcublas-dev=12.4.5.8=0
|
||||
- libcufft=11.2.1.3=0
|
||||
- libcufft-dev=11.2.1.3=0
|
||||
- libcurand=10.4.0.35=0
|
||||
- libcurand-dev=10.4.0.35=0
|
||||
- libcurl=8.15.0=h2300eb9_0
|
||||
- libcusolver=11.6.1.9=0
|
||||
- libcusolver-dev=11.6.1.9=0
|
||||
- libcusparse=12.3.1.170=0
|
||||
- libcusparse-dev=12.3.1.170=0
|
||||
- libdeflate=1.22=h5bf469e_0
|
||||
- libffi=3.4.4=hd77b12b_1
|
||||
- libglib=2.84.2=h405b238_0
|
||||
- libgrpc=1.71.0=hf4237ab_0
|
||||
- libiconv=1.16=h2bbff1b_3
|
||||
- libjpeg-turbo=2.0.0=h196d8e1_0
|
||||
- libnpp=12.2.5.30=0
|
||||
- libnpp-dev=12.2.5.30=0
|
||||
- libnvfatbin=13.0.39=0
|
||||
- libnvfatbin-dev=13.0.39=0
|
||||
- libnvjitlink=12.4.127=0
|
||||
- libnvjitlink-dev=12.4.127=0
|
||||
- libnvjpeg=12.3.1.117=0
|
||||
- libnvjpeg-dev=12.3.1.117=0
|
||||
- libpng=1.6.39=h8cc25b3_0
|
||||
- libprotobuf=5.29.3=h65a231f_1
|
||||
- libre2-11=2024.07.02=hd248061_3
|
||||
- libssh2=1.11.1=h2addb87_0
|
||||
- libthrift=0.15.0=ha2884a9_3
|
||||
- libtiff=4.7.0=h404307b_0
|
||||
- libuv=1.48.0=h827c3e9_0
|
||||
- libwebp=1.3.2=h18467be_1
|
||||
- libwebp-base=1.3.2=h3d04722_1
|
||||
- libxml2=2.13.8=h866ff63_0
|
||||
- lz4-c=1.9.4=h2bbff1b_1
|
||||
- markupsafe=3.0.2=py312h827c3e9_0
|
||||
- mkl=2023.1.0=h6b88ed4_46358
|
||||
- mkl-service=2.4.0=py312h827c3e9_2
|
||||
- mkl_fft=1.3.11=py312h827c3e9_0
|
||||
- mkl_random=1.2.8=py312h0158946_0
|
||||
- mpc=1.3.1=h827c3e9_0
|
||||
- mpfr=4.2.1=h56c3642_0
|
||||
- mpmath=1.3.0=py312haa95532_0
|
||||
- multidict=6.6.3=pyh62beb40_0
|
||||
- multiprocess=0.70.15=py312haa95532_0
|
||||
- networkx=3.5=py312haa95532_0
|
||||
- numexpr=2.11.0=py312hdb065b2_0
|
||||
- numpy=2.3.1=py312h5f75535_0
|
||||
- numpy-base=2.3.1=py312h23d94f8_0
|
||||
- openjpeg=2.5.2=h9b5d1b5_1
|
||||
- openssl=3.5.2=h725018a_0
|
||||
- orc=2.1.1=hd1c1d5c_0
|
||||
- packaging=25.0=pyh29332c3_1
|
||||
- pandas=2.3.2=py312ha5e6156_0
|
||||
- pcre2=10.42=h0ff8eda_1
|
||||
- pillow=11.3.0=py312hb328d1f_0
|
||||
- pip=25.2=pyhc872135_0
|
||||
- pixman=0.46.4=h4043f72_0
|
||||
- propcache=0.3.1=pyhe1237c8_0
|
||||
- psutil=5.9.0=py312h827c3e9_1
|
||||
- pyarrow=19.0.0=py312h5da7b33_1
|
||||
- pycparser=2.21=pyhd3eb1b0_0
|
||||
- pysocks=1.7.1=py312haa95532_0
|
||||
- python=3.12.11=h716150d_0
|
||||
- python-dateutil=2.9.0.post0=pyhe01879c_2
|
||||
- python-tzdata=2025.2=pyhd8ed1ab_0
|
||||
- python-xxhash=3.5.0=py312h827c3e9_0
|
||||
- pytorch=2.5.1=py3.12_cuda12.4_cudnn9_0
|
||||
- pytorch-cuda=12.4=h3fd98bf_7
|
||||
- pytorch-mutex=1.0=cuda
|
||||
- pytz=2025.2=pyhd8ed1ab_0
|
||||
- pyyaml=6.0.2=py312h827c3e9_0
|
||||
- re2=2024.07.02=haf4117d_3
|
||||
- regex=2024.11.6=py312h827c3e9_0
|
||||
- requests=2.32.5=py312haa95532_0
|
||||
- safetensors=0.5.3=py312h44068b5_0
|
||||
- setuptools=72.1.0=py312haa95532_0
|
||||
- six=1.17.0=pyhe01879c_1
|
||||
- snappy=1.2.2=h7fa0ca8_0
|
||||
- sqlite=3.50.2=hda9a48d_1
|
||||
- sympy=1.14.0=py312haa95532_0
|
||||
- tbb=2021.8.0=h59b6b97_0
|
||||
- tk=8.6.15=hf199647_0
|
||||
- tokenizers=0.21.0=py312h482ea96_0
|
||||
- tqdm=4.67.1=pyhd8ed1ab_1
|
||||
- transformers=4.55.4=pyhd8ed1ab_0
|
||||
- typing-extensions=4.15.0=py312haa95532_0
|
||||
- typing_extensions=4.15.0=py312haa95532_0
|
||||
- tzdata=2025b=h04d1e81_0
|
||||
- ucrt=10.0.22621.0=haa95532_0
|
||||
- urllib3=2.5.0=py312haa95532_0
|
||||
- utf8proc=2.6.1=h2bbff1b_1
|
||||
- vc=14.42=haa95532_5
|
||||
- vc14_runtime=14.44.35208=h4927774_10
|
||||
- vs2015_runtime=14.44.35208=ha6b5a95_10
|
||||
- wheel=0.45.1=py312haa95532_0
|
||||
- win_inet_pton=1.1.0=py312haa95532_0
|
||||
- xxhash=0.8.0=h8ffe710_3
|
||||
- xz=5.6.4=h4754444_1
|
||||
- yaml=0.2.5=he774522_0
|
||||
- yarl=1.20.1=pyhe1237c8_0
|
||||
- zlib=1.2.13=h8cc25b3_1
|
||||
- zstd=1.5.6=h8880b57_0
|
||||
- pip:
|
||||
- torchaudio==2.5.1
|
||||
- torchvision==0.20.1
|
||||
@@ -1,137 +1,10 @@
|
||||
from transformers import WhisperProcessor, WhisperForConditionalGeneration
|
||||
import torch
|
||||
import torchaudio
|
||||
import logging
|
||||
import time
|
||||
from tqdm import tqdm
|
||||
from transcription.audio_transcription import AudioTranscription
|
||||
from transcription.torch_checker import check_torch
|
||||
from utils.logger import setup_logger
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = setup_logger("main")
|
||||
|
||||
print("=== Checking PyTorch ===")
|
||||
print(f"Torch version: {torch.version}")
|
||||
print(f"CUDA is available: {torch.cuda.is_available()}")
|
||||
if torch.cuda.is_available():
|
||||
print(f"CUDA version: {torch.version.cuda}")
|
||||
print(f"Number of GPU: {torch.cuda.device_count()}")
|
||||
print(f"Name of GPU: {torch.cuda.get_device_name(0)}")
|
||||
print("=== Check completed ===")
|
||||
|
||||
class AudioTranscription:
|
||||
model_name = "openai/whisper-large-v2"
|
||||
|
||||
filepath: str
|
||||
waveform: torch.Tensor
|
||||
sampling_rate: int
|
||||
|
||||
chunks: list = []
|
||||
# one chunk size in seconds
|
||||
chunk_size: int
|
||||
device = "cuda"
|
||||
processor: WhisperProcessor
|
||||
model: WhisperForConditionalGeneration
|
||||
# self.device here and all previous shit
|
||||
|
||||
language = "ru"
|
||||
|
||||
all_transcription: list = []
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
filepath: str,
|
||||
language = "ru",
|
||||
device = "cuda",
|
||||
model_name = "openai/whisper-large-v2"
|
||||
) -> None:
|
||||
self.filepath = filepath
|
||||
self.language = language
|
||||
self.device = device
|
||||
self.model_name = model_name
|
||||
self.chunks: list = []
|
||||
try:
|
||||
logger.info("Loading model WhisperProcessor...")
|
||||
self.processor = WhisperProcessor.from_pretrained(self.model_name)
|
||||
|
||||
self.model = WhisperForConditionalGeneration.from_pretrained(
|
||||
self.model_name,
|
||||
torch_dtype=torch.float16,
|
||||
device_map="auto"
|
||||
).to(self.device)
|
||||
|
||||
logger.info("Model loaded.")
|
||||
|
||||
self.waveform, self.sampling_rate = torchaudio.load(filepath, format="mp3", backend="ffmpeg")
|
||||
logger.info(f"Successfully loaded file {filepath}.")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unable to load file {self.filepath}: {e}")
|
||||
raise
|
||||
|
||||
def resample(self) -> None:
|
||||
self.waveform = torchaudio.functional.resample(self.waveform, self.sampling_rate, 16000)
|
||||
|
||||
def to_mono(self):
|
||||
if self.waveform.shape[0] > 1:
|
||||
self.waveform = self.waveform.mean(dim=0, keepdim=True)
|
||||
self.waveform = self.waveform.squeeze(0)
|
||||
|
||||
def split_to_chunks(self, chunk_length_s: int = 30) -> None:
|
||||
logger.info(f"Splitting audio on chunks...")
|
||||
|
||||
self.chunk_size = chunk_length_s * 16000 # 16kHz after resampling
|
||||
total_samples = self.waveform.shape[0]
|
||||
chunks_count = (total_samples + self.chunk_size - 1) // self.chunk_size
|
||||
|
||||
logger.info(f"File length - {total_samples / 16000:.1f} seconds, splitting on {chunks_count} chunks by {chunk_length_s} seconds per chunk.")
|
||||
|
||||
self.chunks = []
|
||||
for idx in range(chunks_count):
|
||||
start = idx * self.chunk_size
|
||||
end = min((idx + 1) * self.chunk_size, total_samples)
|
||||
chunk = self.waveform[start:end].cpu().numpy().astype("float32")
|
||||
self.chunks.append(chunk)
|
||||
|
||||
def process_chunk(
|
||||
self,
|
||||
chunk
|
||||
) -> str:
|
||||
inputs = self.processor(chunk, sampling_rate=16000, return_tensors="pt")
|
||||
input_features = inputs.input_features.to(self.device).to(torch.float16)
|
||||
|
||||
with torch.no_grad():
|
||||
predicted_ids = self.model.generate(
|
||||
input_features,
|
||||
language=self.language,
|
||||
task="transcribe",
|
||||
temperature=0.0
|
||||
)
|
||||
|
||||
text = self.processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
|
||||
|
||||
return text
|
||||
|
||||
def process_all_chunks(self) -> None:
|
||||
start_time = time.time()
|
||||
|
||||
try:
|
||||
for chunk_idx in tqdm(range(len(self.chunks))):
|
||||
self.all_transcription.append(self.process_chunk(self.chunks[chunk_idx]))
|
||||
|
||||
end_time = time.time()
|
||||
logger.info(f"Transcription completed in {end_time - start_time:.2f} seconds")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Errors occured while processing chunks: {e}")
|
||||
|
||||
def transcribe_audio(self) -> str:
|
||||
self.resample()
|
||||
self.to_mono()
|
||||
self.split_to_chunks()
|
||||
self.process_all_chunks()
|
||||
return " ".join(self.all_transcription)
|
||||
check_torch()
|
||||
|
||||
try:
|
||||
track = AudioTranscription("sample.mp3")
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
$envName = "notecast"
|
||||
|
||||
Write-Output >>> Creating environment $envName from environment.yml"
|
||||
conda env create -f environment.yml -n $envName
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Output ">>> Environment already exists, updating..."
|
||||
conda env update -f environment.yml --prune
|
||||
}
|
||||
|
||||
Write-Output ">>> Activating environment"
|
||||
conda activate $envName
|
||||
|
||||
Write-Output ">>> Download completed!"
|
||||
+10
-5
@@ -1,8 +1,13 @@
|
||||
# python -m venv .venv
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# pip install -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cu128
|
||||
ENV_NAME="notecast"
|
||||
|
||||
conda init -c speech-to-conspect
|
||||
echo ">>> Creating environment $ENV_NAME from environment.yml"
|
||||
conda env create -f environment.yml || conda env update -f environment.yml --prune
|
||||
|
||||
conda install pytorch torchvision torchaudio -c pytorch -c nvidia
|
||||
conda install accelerate transformers ffmpeg -c conda-forge
|
||||
echo ">>> Activating environment"
|
||||
eval "$(conda shell.bash hook)"
|
||||
conda activate "$ENV_NAME"
|
||||
|
||||
echo ">>> Download completed!"
|
||||
@@ -0,0 +1,143 @@
|
||||
from transformers import WhisperProcessor, WhisperForConditionalGeneration
|
||||
import torch
|
||||
import torchaudio
|
||||
from utils.logger import setup_logger
|
||||
import time
|
||||
import math
|
||||
from tqdm import tqdm
|
||||
|
||||
logger = setup_logger("AudioTranscribe module")
|
||||
|
||||
class AudioTranscription:
|
||||
model_name = "openai/whisper-large-v2"
|
||||
|
||||
filepath: str
|
||||
waveform: torch.Tensor
|
||||
sampling_rate: int
|
||||
|
||||
chunks: list = []
|
||||
chunk_size: int
|
||||
device = "cuda"
|
||||
processor: WhisperProcessor
|
||||
model: WhisperForConditionalGeneration
|
||||
|
||||
language = "ru"
|
||||
|
||||
all_transcription: list = []
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
filepath: str,
|
||||
language = "ru",
|
||||
device = "cuda",
|
||||
model_name = "openai/whisper-large-v2"
|
||||
) -> None:
|
||||
self.filepath = filepath
|
||||
self.language = language
|
||||
self.device = device
|
||||
self.model_name = model_name
|
||||
self.chunks: list = []
|
||||
try:
|
||||
logger.info("Loading model WhisperProcessor...")
|
||||
self.processor = WhisperProcessor.from_pretrained(self.model_name)
|
||||
|
||||
self.model = WhisperForConditionalGeneration.from_pretrained(
|
||||
self.model_name,
|
||||
torch_dtype=torch.float16,
|
||||
device_map="auto"
|
||||
).to(self.device)
|
||||
|
||||
logger.info("Model loaded.")
|
||||
|
||||
self.waveform, self.sampling_rate = torchaudio.load(filepath, format="mp3", backend="ffmpeg")
|
||||
logger.info(f"Successfully loaded file {filepath}.")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unable to load file {self.filepath}: {e}")
|
||||
raise
|
||||
|
||||
def resample(self) -> None:
|
||||
self.waveform = torchaudio.functional.resample(self.waveform, self.sampling_rate, 16000)
|
||||
|
||||
def to_mono(self):
|
||||
if self.waveform.shape[0] > 1:
|
||||
self.waveform = self.waveform.mean(dim=0, keepdim=True)
|
||||
self.waveform = self.waveform.squeeze(0)
|
||||
|
||||
def split_to_chunks(self, chunk_length_s: int = 30) -> None:
|
||||
logger.info(f"Splitting audio on chunks...")
|
||||
|
||||
self.chunk_size = chunk_length_s * 16000 # 16kHz after resampling
|
||||
total_samples = self.waveform.shape[0]
|
||||
chunks_count = (total_samples + self.chunk_size - 1) // self.chunk_size
|
||||
|
||||
logger.info(f"File length - {total_samples / 16000:.1f} seconds, splitting on {chunks_count} chunks by {chunk_length_s} seconds per chunk.")
|
||||
|
||||
self.chunks = []
|
||||
for idx in range(chunks_count):
|
||||
start = idx * self.chunk_size
|
||||
end = min((idx + 1) * self.chunk_size, total_samples)
|
||||
chunk = self.waveform[start:end].cpu().numpy().astype("float32")
|
||||
self.chunks.append(chunk)
|
||||
|
||||
def process_chunk(
|
||||
self,
|
||||
chunk
|
||||
) -> str:
|
||||
inputs = self.processor(chunk, sampling_rate=16000, return_tensors="pt")
|
||||
input_features = inputs.input_features.to(self.device).to(torch.float16)
|
||||
|
||||
with torch.no_grad():
|
||||
predicted_ids = self.model.generate(
|
||||
input_features,
|
||||
language=self.language,
|
||||
task="transcribe",
|
||||
temperature=0.0
|
||||
)
|
||||
|
||||
text = self.processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
|
||||
|
||||
return text
|
||||
|
||||
def process_all_chunks(self, batch_size: int = 16) -> None:
|
||||
start_time = time.time()
|
||||
try:
|
||||
self.all_transcription = []
|
||||
|
||||
for i in tqdm(range(math.ceil(len(self.chunks) / batch_size))):
|
||||
# TODO: rewrite batching as a separate function
|
||||
batch = self.chunks[i*batch_size:(i+1)*batch_size]
|
||||
|
||||
inputs = self.processor(
|
||||
batch,
|
||||
sampling_rate=16000,
|
||||
return_tensors="pt",
|
||||
padding=True
|
||||
)
|
||||
|
||||
input_features = inputs.input_features.to(self.device).to(torch.float16)
|
||||
|
||||
with torch.no_grad():
|
||||
predicted_ids = self.model.generate(
|
||||
input_features,
|
||||
language=self.language,
|
||||
task="transcribe",
|
||||
temperature=0.0
|
||||
)
|
||||
|
||||
texts = self.processor.batch_decode(predicted_ids, skip_special_tokens=True)
|
||||
self.all_transcription.extend(texts)
|
||||
|
||||
end_time = time.time()
|
||||
logger.info(f"Transcription completed in {end_time - start_time:.2f} seconds")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Errors occured while processing chunks: {e}")
|
||||
|
||||
|
||||
def transcribe_audio(self) -> str:
|
||||
self.resample()
|
||||
self.to_mono()
|
||||
self.split_to_chunks()
|
||||
self.process_all_chunks()
|
||||
return " ".join(self.all_transcription)
|
||||
@@ -0,0 +1,11 @@
|
||||
import torch
|
||||
|
||||
def check_torch() -> None:
|
||||
print("=== Checking PyTorch ===")
|
||||
print(f"Torch version: {torch.version}")
|
||||
print(f"CUDA is available: {torch.cuda.is_available()}")
|
||||
if torch.cuda.is_available():
|
||||
print(f"CUDA version: {torch.version.cuda}")
|
||||
print(f"Number of GPU: {torch.cuda.device_count()}")
|
||||
print(f"Name of GPU: {torch.cuda.get_device_name(0)}")
|
||||
print("=== Check completed ===")
|
||||
@@ -1 +1,13 @@
|
||||
# empty((
|
||||
import tkinter as tk
|
||||
|
||||
root = tk.Tk()
|
||||
root.title("Audio Transcriptor")
|
||||
root.geometry("800x600")
|
||||
|
||||
path_entry = tk.Entry(root, width=40)
|
||||
path_entry.pack(padx=10, pady=(5, 10))
|
||||
|
||||
transcribe_button = tk.Button(text="Transcribe")
|
||||
transcribe_button.pack(anchor="e", rely=25, relx=15)
|
||||
|
||||
root.mainloop()
|
||||
@@ -0,0 +1,36 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
def setup_logger(
|
||||
name: str = __name__,
|
||||
level: int = logging.INFO,
|
||||
log_to_file: bool = False,
|
||||
filename: str = "app.log"
|
||||
) -> logging.Logger:
|
||||
"""
|
||||
Logger configuration with output to command line and (optional) to file
|
||||
|
||||
:param name: logger name
|
||||
:param level: logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
:param log_to_file: logging to filename
|
||||
:param filename: filename for logs
|
||||
:return: logger instance
|
||||
"""
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(level)
|
||||
|
||||
formatter = logging.Formatter(
|
||||
fmt="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setFormatter(formatter)
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
if log_to_file:
|
||||
file_handler = logging.FileHandler(filename, encoding="utf-8")
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
return logger
|
||||
Reference in New Issue
Block a user