cutted 0.2.0__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cutted/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.1.0"
1
+ __version__ = "0.3.1"
2
2
  __author__ = "simon0302010"
cutted/app.py CHANGED
@@ -8,14 +8,25 @@ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
8
8
 
9
9
  customtkinter.set_appearance_mode("Dark")
10
10
 
11
+ try:
12
+ from .core import transcribe
13
+ whisper_support = True
14
+ print_info("Whisper support present.")
15
+ except:
16
+ whisper_support = False
17
+ print_info("Whisper support is not present.")
18
+
11
19
  class CuttedApp:
12
20
  def __init__(self):
13
21
  self.AudioProcessor = audio_processor.AudioProcessor()
22
+ if whisper_support:
23
+ self.whisper = None
14
24
  self.gemini = gemini.GeminiClient()
15
25
  self.canvas = None
16
26
  self.cursor_line = None
17
27
  self.last_slider_update = 0
18
28
  self.is_playing = False
29
+ self.last_states = []
19
30
  self.setup_ui()
20
31
 
21
32
  def setup_ui(self):
@@ -40,12 +51,24 @@ class CuttedApp:
40
51
 
41
52
  export_button = customtkinter.CTkButton(self.root, text="Export", command=self.export_audio, width=70)
42
53
  export_button.place(relx=0.9, rely=1.0, anchor="s", y=-30)
54
+
55
+ undo_button = customtkinter.CTkButton(self.root, text="Undo", command=self.undo_last, width=70)
56
+ undo_button.place(relx=0.1, rely=1.0, anchor="s", y=-30)
57
+
58
+ if whisper_support:
59
+ self.use_transcript_checkbox = customtkinter.CTkCheckBox(
60
+ self.root,
61
+ text="Give Gemini a transcript (very slow)",
62
+ text_color="#888888",
63
+ font=("Arial", 12)
64
+ )
65
+ self.use_transcript_checkbox.place(relx=0.0, rely=1.0, anchor="w", y=-12)
43
66
 
44
67
  self.play_button = customtkinter.CTkButton(self.root, text="Play", command=self.play_audio, width=50)
45
68
  self.play_button.place(relx=0.3, rely=1.0, anchor="s", y=-30)
46
69
  self.stop_button = customtkinter.CTkButton(self.root, text="Stop", command=self.stop_audio, width=50)
47
70
  self.stop_button.place(relx=0.7, rely=1.0, anchor="s", y=-30)
48
-
71
+
49
72
  self.input_frame = customtkinter.CTkFrame(self.root, fg_color="transparent", height=36)
50
73
  self.input_frame.place(relx=0.5, rely=1.0, anchor="s", y=-90, relwidth=0.8)
51
74
 
@@ -153,12 +176,21 @@ class CuttedApp:
153
176
  print_success(f"Audio exported to {save_path}")
154
177
 
155
178
  def send_prompt(self):
179
+ self.save_state()
180
+
156
181
  if not hasattr(self.AudioProcessor, "audio") or self.AudioProcessor.audio is None:
157
182
  print_fail("No audio loaded.")
158
183
  return
159
184
 
160
185
  text = self.entry.get()
161
186
  full_prompt = f"You are a audio editing AI. You are controllable via natural language and editing a audio file. The audio file is {round(self.AudioProcessor.get_lenght())}s long."
187
+ if whisper_support:
188
+ if self.use_transcript_checkbox.get():
189
+ if not self.whisper:
190
+ messagebox.showinfo("Info", "Loading Whisper model. This may take a few minutes depending on your internet connection. See the progress in your command line. If this window appears to be frozen, the transcription is running.")
191
+ self.whisper = transcribe.Whisper()
192
+ transcript = self.whisper.transcribe(self.AudioProcessor.audio_path)
193
+ full_prompt += f"\nThis is a transcript with per word timestamps of the audio:\n{transcript}"
162
194
  full_prompt += f"\n\nUser Prompt: {text}"
163
195
  self.entry.delete(0, "end")
164
196
 
@@ -178,9 +210,25 @@ class CuttedApp:
178
210
  else:
179
211
  print_fail("Gemini returned no data")
180
212
 
213
+ def save_state(self):
214
+ if hasattr(self.AudioProcessor, "audio") and self.AudioProcessor.audio is not None:
215
+ self.last_states.append(self.AudioProcessor.audio._spawn(self.AudioProcessor.audio.raw_data))
216
+ if len(self.last_states) > 10:
217
+ self.last_states.pop(0)
218
+
219
+ def undo_last(self):
220
+ if len(self.last_states) == 0:
221
+ print_warn("No previous states to undo")
222
+ messagebox.showwarning("Warning", "No previous states to undo")
223
+ return
224
+
225
+ self.AudioProcessor.audio = self.last_states.pop()
226
+ self.update_plot()
227
+ print_info("Undid last action")
228
+
181
229
  def run(self):
182
230
  self.root.mainloop()
183
231
 
184
232
  def main():
185
233
  app = CuttedApp()
186
- app.run()
234
+ app.run()
cutted/core/transcribe.py CHANGED
@@ -2,7 +2,7 @@ import json
2
2
  import whisper_timestamped as whisper
3
3
 
4
4
  class Whisper:
5
- def __init__(self, model_size: str = "small", device: str = "cpu"):
5
+ def __init__(self, model_size: str = "small", device = None):
6
6
  self.model = whisper.load_model(
7
7
  model_size, device=device
8
8
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cutted
3
- Version: 0.2.0
3
+ Version: 0.3.1
4
4
  Summary: AI-powered audio editor controllable via natural language.
5
5
  Author-email: simon0302010 <simon0302010@gmail.com>
6
6
  License-Expression: GPL-3.0
@@ -15,6 +15,8 @@ Requires-Dist: pydub
15
15
  Requires-Dist: pygame
16
16
  Requires-Dist: google-genai
17
17
  Requires-Dist: python-dotenv
18
+ Provides-Extra: whisper
19
+ Requires-Dist: whisper-timestamped; extra == "whisper"
18
20
  Dynamic: license-file
19
21
 
20
22
  # Cutted
@@ -0,0 +1,12 @@
1
+ cutted/__init__.py,sha256=Q7ZgbkmUOc-Gzy42zzZcKnzKxdZ023pITyXAC0BDBlM,49
2
+ cutted/__main__.py,sha256=lYGLgtIZ_vGZIJmWG6ZQoqOdyOJnaWEA4NBn5Rc7Q8E,61
3
+ cutted/app.py,sha256=xf5LFHdPLz1WNP05eRruHX2hKnaei8CUrqzVSODweAM,8952
4
+ cutted/core/audio_processor.py,sha256=7-XCuPPTlozeuaD2LqyzwRGinu0NvowTLbAh2X4XJ98,5182
5
+ cutted/core/gemini.py,sha256=Ts_EbC1-rO9jIsdSlzKcmjLVS1o663GmfTdzmix12kE,2872
6
+ cutted/core/logger.py,sha256=AjqrgW2LV9HdPkPQ8oOmyd9lWzVSIg46r74ILR7mVHo,585
7
+ cutted/core/transcribe.py,sha256=0e7aCva4y6D-gKe1xw5HT9VoFgbvHGgV6utn12r8wXA,986
8
+ cutted-0.3.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
9
+ cutted-0.3.1.dist-info/METADATA,sha256=6plv-IaqUXQeeAnChYaMBjYSLh8FBTAtvyQqZkRTuuA,1201
10
+ cutted-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ cutted-0.3.1.dist-info/top_level.txt,sha256=PL6glZvzRyKWCDn5aoYI9uH8HlEA5Qd_XFJowJKARYI,7
12
+ cutted-0.3.1.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- cutted/__init__.py,sha256=CP0x3JIScNbFVSOoF3eIQTKD5gDRfWXcCFE46rlZCio,49
2
- cutted/__main__.py,sha256=lYGLgtIZ_vGZIJmWG6ZQoqOdyOJnaWEA4NBn5Rc7Q8E,61
3
- cutted/app.py,sha256=qZ6idEqEmdtCLOahBN4803u-t12oNRhTAgbN3XiIiKY,6803
4
- cutted/core/audio_processor.py,sha256=7-XCuPPTlozeuaD2LqyzwRGinu0NvowTLbAh2X4XJ98,5182
5
- cutted/core/gemini.py,sha256=Ts_EbC1-rO9jIsdSlzKcmjLVS1o663GmfTdzmix12kE,2872
6
- cutted/core/logger.py,sha256=AjqrgW2LV9HdPkPQ8oOmyd9lWzVSIg46r74ILR7mVHo,585
7
- cutted/core/transcribe.py,sha256=cm6ziM3_grXKpUCFHiAU7-6lFK_SVsf7-6n14vMYQng,992
8
- cutted-0.2.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
9
- cutted-0.2.0.dist-info/METADATA,sha256=4hl_l2XcGg74HKYMcbAlklxduA8nw066deSAVBBuvOs,1122
10
- cutted-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
- cutted-0.2.0.dist-info/top_level.txt,sha256=PL6glZvzRyKWCDn5aoYI9uH8HlEA5Qd_XFJowJKARYI,7
12
- cutted-0.2.0.dist-info/RECORD,,
File without changes