Skip to content

Commit

Permalink
Merge pull request #26 from math-pixel/23-add-a-state-system-in-the-t…
Browse files Browse the repository at this point in the history
…ranscribtioncontroller

23 add a state system in the transcribtioncontroller
  • Loading branch information
EthanCarollo committed Mar 18, 2024
2 parents 826f528 + 4fd7bc9 commit 5072451
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 21 deletions.
49 changes: 42 additions & 7 deletions transcription/TranscriptionController.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
from downloader.DownloaderManager import *
from convertor.ConversionCoordinator import *
from transcriber.TranscriberManager import *
from enum import Enum
from transcription.TranscriptionObserver import *

class TranscriptionState(Enum):
IDLE = "IDLE"
DOWNLOADINGVIDEO = "DOWNLOADINGVIDEO"
CONVERTINGVIDEO = "CONVERTINGVIDEO"
LOADINGMODEL = "LOADINGMODEL"
TRANSCRIBING = "TRANSCRIBING"

from enum import Enum

Expand All @@ -19,6 +28,7 @@ class TranscriptionState(Enum):
TRANSCRIBING = "TRANSCRIBING"

# I named this class a controller cause the controller need to process the user input
# This controller is also an Observable object lol : a singleton facade observable lol
class TranscriptionController:

instance = None
Expand All @@ -30,31 +40,56 @@ def __init__(self):
contextTranscriber = IATranscriberContext("small")
self.trManager = TranscriberManager()
self.trManager.setCurrentAI(ListAI.WHISPER, contextTranscriber)
self.state = TranscriptionState.LOADINGMODEL
self.trSubscribers = [] # This is an array of TranscriptionObserver
pass

# The main function that we need to call, here, the input is only a string
# cause the only way for the user to talk with this object is by passing an
# input text that contains the url // the path of the video
# We may need to thread that in the future
# The callback of this function take a value in parameter so, in this callback, you will need
# to put something like trContext.text = result["text"]
def startTranscription(self, input: str):
transcriberContext = TranscriberContext(input)

# TODO Decomment this lines or DONT COMMIT THIS FILE
self.updateState(TranscriptionState.DOWNLOADINGVIDEO)
downloaderManager = DownloaderManager()
downloaderManager.startDownload(transcriberContext)

# TODO ERASE OR UNCOMMENT this lines if you wan't to test without download
# downloaderManager = DownloaderManager()
# downloaderManager.startDownload(transcriberContext)
# transcriberContext.inputPath = "./export/video.mp4"

transcriberContext.inputPath = "./export/video.mp4"

self.updateState(TranscriptionState.CONVERTINGVIDEO)
converterCoordinator = ConversionCoordinator.getConversionCoordinator()
conversionResult = converterCoordinator.convert(transcriberContext)

return self.trManager.transcribe(transcriberContext.audioPath)
self.updateState(TranscriptionState.TRANSCRIBING)
result = self.trManager.transcribe(transcriberContext.audioPath)
self.updateState(TranscriptionState.IDLE)
return result

# Update the state of the controller
def updateState(self, state):
DLog.goodlog("updated state into " + str(state))
# In this function, we will set the state and
# TODO : NOTIFY SUBSCRIBERS THAT THE STATE CHANGED CAUSE THIS OBJECT IS AN OBSERVABLE
for sub in self.trSubscribers :
if isinstance(sub, TranscriptionObserver) == False:
DLog.bigerrorlog("You didn't put a Transcription Observer in the trSubscribers Array !!")
sub.update(state)
self.state = state

def addSubscriber(self, subscriber):
self.trSubscribers.append(subscriber)

def removeSubscriber(self, subscriber):
# After you added a subscriber, if you don't use it in the future, DELETE IT PLZ !!!!
self.trSubscribers.remove(subscriber)

# For some reason, this function worked as a static even without the @staticmethod... so i searched and lol
# https://stackoverflow.com/questions/52831534/why-is-a-method-of-a-python-class-declared-without-self-and-without-decorators
# This is funny, what a snake
# This is funny, what a snake (python lol)
@staticmethod
def getInstance() -> 'TranscriptionController' :
if TranscriptionController.instance == None :
Expand Down
10 changes: 10 additions & 0 deletions transcription/TranscriptionObserver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# This is the observer class of the Transcription Observer, to do this, i checked that :
# https://refactoring.guru/fr/design-patterns/observer
class TranscriptionObserver:
def __init__(self):
pass

def update(self, state):
DLog.goodlog(state)
pass
43 changes: 34 additions & 9 deletions window/scene/LoadingScene.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QProgressBar, QSizePolicy
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QDesktopWidget, QSizePolicy, QProgressBar
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtGui import QDragEnterEvent, QDropEvent
from Utils import Utils
from DLog import *
from transcription.TranscriptionController import *
from transcription.TranscriptionController import TranscriptionState

import threading
import math

# This is the loading scene called after the MainScene, this will need some improvements
class LoadingScene(QWidget):
class LoadingScene(QWidget, TranscriptionObserver):
def __init__(self):
super().__init__()

Expand Down Expand Up @@ -35,42 +40,62 @@ def __init__(self):
self.showIdleState()
self.showDownloadState()

# Here it is the function update that came from the TranscriptionObserver
def update(self, state):
if state == TranscriptionState.IDLE:
self.showIdleState()
pass
elif state == TranscriptionState.DOWNLOADINGVIDEO:
self.showDownloadState()
pass
elif state == TranscriptionState.CONVERTINGVIDEO:
self.showConvertState()
pass
elif state == TranscriptionState.LOADINGMODEL:
self.showLoadModelState()
pass
elif state == TranscriptionState.TRANSCRIBING:
self.showTranscribeState()
pass
else:
raise Exception("State isn't implemented in the Loading Scene")


def showIdleState(self):
self.completed += 1
value = self.completed / self.stateCount * 100
value = math.floor(self.completed / self.stateCount * 100)
self.progress.setValue(value)

self.labelState.setText("Idle...")


def showDownloadState(self):
self.completed += 1
value = self.completed / self.stateCount * 100
value = math.floor(self.completed / self.stateCount * 100)
self.progress.setValue(value)

self.labelState.setText("Downloading media...")


def showConvertState(self):
self.completed += 1
value = self.completed / self.stateCount * 100
value = math.floor(self.completed / self.stateCount * 100)
self.progress.setValue(value)

self.labelState.setText("Converting...")


def showLoadModelState(self):
self.completed += 1
value = self.completed / self.stateCount * 100
value = math.floor(self.completed / self.stateCount * 100)
self.progress.setValue(value)

self.labelState.setText("Loading model...")


def showTranscribeState(self):
self.completed += 1
value = self.completed / self.stateCount * 100
value = math.floor(self.completed / self.stateCount * 100)
self.progress.setValue(value)

self.labelState.setText("Transcribing...")
Expand Down
18 changes: 13 additions & 5 deletions window/scene/mainScene/DragAndDrop.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@
from PyQt5.QtCore import Qt, QUrl, QThread, pyqtSignal
from PyQt5.QtGui import QDragEnterEvent, QDropEvent
from Utils import Utils
from transcription.TranscriptionController import *
from transcription.TranscriptionObserver import *
from window.scene.VideoTranscribedScene import *
from window.scene.LoadingScene import *
import threading

class TranscribeVideoThread(QThread):
# Here, we signal that the pyqtSignal take 1 arg and it is a list
finished_signal = pyqtSignal(list)
update_state_signal = pyqtSignal(TranscriptionState)

def __init__(self, url):
def __init__(self, url, loadingScene):
super().__init__()
self.url = url
self.loadingScene = loadingScene;

def run(self):
result = TranscriptionController.getInstance().startTranscription(self.url);
trController = TranscriptionController.getInstance()
trController.addSubscriber(self.loadingScene)
result = trController.startTranscription(self.url);
trController.removeSubscriber(self.loadingScene)
self.finished_signal.emit(result["segments"])

class DragAndDrop(QWidget):
Expand Down Expand Up @@ -98,14 +103,17 @@ def dropEvent(self, event: QDropEvent):
# ---------------------------------------------------------------------------- #
# This is the function called when we click on the button
def launchTranscription(self, url):
self.transcribe_thread = TranscribeVideoThread(url)

loadingScene = LoadingScene()
self.transcribe_thread = TranscribeVideoThread(url, loadingScene)
# Connect the callback to the finished signal !
self.transcribe_thread.finished_signal.connect(self.nextPage)
# TODO : ADD A NEW UPDATE STATE SIGNAL AND CONNECT IT TO THE LOADING SCENE
self.transcribe_thread.start()

# To avoid circular import here lol
from window.SceneManager import SceneManager
SceneManager.getInstance().newScene(LoadingScene())
SceneManager.getInstance().newScene(loadingScene)


def nextPage(self, result: list):
Expand Down

0 comments on commit 5072451

Please sign in to comment.