cutted 0.3.1__py3-none-any.whl → 0.3.2__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.3.1"
1
+ __version__ = "0.3.2"
2
2
  __author__ = "simon0302010"
cutted/app.py CHANGED
@@ -58,11 +58,19 @@ class CuttedApp:
58
58
  if whisper_support:
59
59
  self.use_transcript_checkbox = customtkinter.CTkCheckBox(
60
60
  self.root,
61
- text="Give Gemini a transcript (very slow)",
61
+ text="Send transcript to Gemini (slower, more accurate)",
62
62
  text_color="#888888",
63
63
  font=("Arial", 12)
64
64
  )
65
65
  self.use_transcript_checkbox.place(relx=0.0, rely=1.0, anchor="w", y=-12)
66
+
67
+ self.use_audio_checkbox = customtkinter.CTkCheckBox(
68
+ self.root,
69
+ text="Send audio to Gemini (buggy)",
70
+ text_color="#888888",
71
+ font=("Arial", 12)
72
+ )
73
+ self.use_audio_checkbox.place(relx=1.0, rely=1.0, anchor="e", y=-12)
66
74
 
67
75
  self.play_button = customtkinter.CTkButton(self.root, text="Play", command=self.play_audio, width=50)
68
76
  self.play_button.place(relx=0.3, rely=1.0, anchor="s", y=-30)
@@ -183,32 +191,36 @@ class CuttedApp:
183
191
  return
184
192
 
185
193
  text = self.entry.get()
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}"
194
- full_prompt += f"\n\nUser Prompt: {text}"
195
- self.entry.delete(0, "end")
196
-
197
- function_call, text_result = self.gemini.generate(full_prompt)
198
-
199
- if function_call:
200
- print_info(f"Gemini called {function_call.name}")
201
- if function_call.name == "cut_audio":
202
- print_info("Cut function called")
203
- args = function_call.args
204
- result = self.AudioProcessor.cut(args["start"], args["end"])
205
- if not result:
206
- messagebox.showerror("Error", "Please try again.")
207
- self.update_plot()
208
- elif text_result:
209
- messagebox.showerror("Error", text_result.strip())
210
- else:
211
- print_fail("Gemini returned no data")
194
+ if text.strip():
195
+ 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."
196
+ if whisper_support:
197
+ if self.use_transcript_checkbox.get():
198
+ if not self.whisper:
199
+ 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.")
200
+ self.whisper = transcribe.Whisper()
201
+ transcript = self.whisper.transcribe(self.AudioProcessor.audio_path)
202
+ full_prompt += f"\nThis is a transcript with per word timestamps of the audio:\n{transcript}"
203
+ full_prompt += f"\n\nUser Prompt: {text}"
204
+ self.entry.delete(0, "end")
205
+
206
+ if self.use_audio_checkbox.get():
207
+ function_call, text_result = self.gemini.generate(full_prompt, audio_base64=self.AudioProcessor.get_audio_base64())
208
+ else:
209
+ function_call, text_result = self.gemini.generate(full_prompt)
210
+
211
+ if function_call:
212
+ print_info(f"Gemini called {function_call.name}")
213
+ if function_call.name == "cut_audio":
214
+ print_info("Cut function called")
215
+ args = function_call.args
216
+ result = self.AudioProcessor.cut(args["start"], args["end"])
217
+ if not result:
218
+ messagebox.showerror("Error", "Please try again.")
219
+ self.update_plot()
220
+ elif text_result:
221
+ messagebox.showerror("Error", text_result.strip())
222
+ else:
223
+ print_fail("Gemini returned no data")
212
224
 
213
225
  def save_state(self):
214
226
  if hasattr(self.AudioProcessor, "audio") and self.AudioProcessor.audio is not None:
@@ -4,9 +4,8 @@ from .logger import *
4
4
  import numpy as np
5
5
  from matplotlib.figure import Figure
6
6
  import pygame
7
+ import base64
7
8
  import io
8
- import threading
9
- import time
10
9
 
11
10
  class AudioProcessor:
12
11
  def __init__(self):
@@ -150,4 +149,12 @@ class AudioProcessor:
150
149
  }
151
150
 
152
151
  def export_audio(self, path, format: str = "mp3"):
153
- self.audio.export(path, format=format)
152
+ self.audio.export(path, format=format)
153
+
154
+ def get_audio_base64(self):
155
+ buffer = io.BytesIO()
156
+ self.audio.export(buffer, format="mp3")
157
+ buffer.seek(0)
158
+ audio_bytes = buffer.read()
159
+ audio_base64 = base64.b64encode(audio_bytes)
160
+ return audio_base64
cutted/core/gemini.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  import sys
3
+ import base64
3
4
  from google import genai
4
5
  from google.genai import types
5
6
 
@@ -15,13 +16,21 @@ class GeminiClient:
15
16
  api_key=GEMINI_API_KEY,
16
17
  )
17
18
 
18
- def generate(self, prompt: str, model: str = "gemini-2.0-flash"):
19
+ def generate(self, prompt: str, model: str = "gemini-2.0-flash", audio_base64 = None):
20
+ parts=[
21
+ types.Part.from_text(text=prompt),
22
+ ]
23
+
24
+ if audio_base64:
25
+ parts.append(types.Part.from_bytes(
26
+ mime_type="audio/mpeg",
27
+ data=base64.b64decode(audio_base64)
28
+ ))
29
+
19
30
  contents = [
20
31
  types.Content(
21
32
  role="user",
22
- parts=[
23
- types.Part.from_text(text=prompt),
24
- ],
33
+ parts=parts
25
34
  ),
26
35
  ]
27
36
  tools = [
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.4
2
+ Name: cutted
3
+ Version: 0.3.2
4
+ Summary: AI-powered audio editor controllable via natural language.
5
+ Author-email: simon0302010 <simon0302010@gmail.com>
6
+ License-Expression: GPL-3.0
7
+ Project-URL: Homepage, https://github.com/simon0302010/Cutted
8
+ Requires-Python: <=3.13,>=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: customtkinter
12
+ Requires-Dist: matplotlib
13
+ Requires-Dist: numpy
14
+ Requires-Dist: pydub
15
+ Requires-Dist: pygame
16
+ Requires-Dist: google-genai
17
+ Requires-Dist: python-dotenv
18
+ Provides-Extra: whisper
19
+ Requires-Dist: whisper-timestamped; extra == "whisper"
20
+ Dynamic: license-file
21
+
22
+ ![PyPI](https://img.shields.io/pypi/v/cutted?color=blue)
23
+ ![PyPI - License](https://img.shields.io/pypi/l/lyriks-video)
24
+ ![Hackatime](https://hackatime-badge.hackclub.com/U08HC7N4JJW/Cutted)
25
+
26
+ # Cutted
27
+
28
+ AI-powered audio editor controlled by natural language 🚀
29
+
30
+ Let AI handle your audio editing with simple commands:
31
+ - Automatically detect quiet or loud parts
32
+ - Transcribe audio (if Whisper is installed)
33
+ - Cut, trim, or adjust volume for specific segments
34
+
35
+ ## Installation
36
+
37
+ 1. **Install system dependencies (e.g., FFmpeg).**
38
+ 2. **Install Cutted**
39
+ ```bash
40
+ pip install cutted
41
+ ```
42
+ **With Whisper support**
43
+ ```bash
44
+ pip install cutted[whisper]
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ 1. **Launch the app:**
50
+ ```bash
51
+ python -m cutted
52
+ ```
53
+ 2. **Load an audio file** (MP3, WAV, etc.)
54
+ 3. **Play, Cut, Undo** – all from the GUI or with text commands ✂️
55
+ 4. **Export** as MP3 or WAV
@@ -0,0 +1,12 @@
1
+ cutted/__init__.py,sha256=ttFLenYuOpXQTaR9nB0dF-3zFB_PeksXf9R4r_TB8S8,49
2
+ cutted/__main__.py,sha256=lYGLgtIZ_vGZIJmWG6ZQoqOdyOJnaWEA4NBn5Rc7Q8E,61
3
+ cutted/app.py,sha256=Ay_yVrPt1TQAE3lqmrII88lFoGZb5Mh5cDwediM9ZG8,9592
4
+ cutted/core/audio_processor.py,sha256=JdPeWO_jAIn_uZFeZYQJX3RC0Vy8GClKrX7xGk4pXR4,5426
5
+ cutted/core/gemini.py,sha256=yHsQXk4tDHcW5qJBuL2LpPvdChimxlmEbu76BvsoeY4,3108
6
+ cutted/core/logger.py,sha256=AjqrgW2LV9HdPkPQ8oOmyd9lWzVSIg46r74ILR7mVHo,585
7
+ cutted/core/transcribe.py,sha256=0e7aCva4y6D-gKe1xw5HT9VoFgbvHGgV6utn12r8wXA,986
8
+ cutted-0.3.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
9
+ cutted-0.3.2.dist-info/METADATA,sha256=MPuSW4_LjNch0PXeFrGtRW1C4CuJ7unNv1ZZhvFHmSM,1503
10
+ cutted-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ cutted-0.3.2.dist-info/top_level.txt,sha256=PL6glZvzRyKWCDn5aoYI9uH8HlEA5Qd_XFJowJKARYI,7
12
+ cutted-0.3.2.dist-info/RECORD,,
@@ -1,68 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: cutted
3
- Version: 0.3.1
4
- Summary: AI-powered audio editor controllable via natural language.
5
- Author-email: simon0302010 <simon0302010@gmail.com>
6
- License-Expression: GPL-3.0
7
- Project-URL: Homepage, https://github.com/simon0302010/Cutted
8
- Requires-Python: <=3.13,>=3.9
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: customtkinter
12
- Requires-Dist: matplotlib
13
- Requires-Dist: numpy
14
- Requires-Dist: pydub
15
- Requires-Dist: pygame
16
- Requires-Dist: google-genai
17
- Requires-Dist: python-dotenv
18
- Provides-Extra: whisper
19
- Requires-Dist: whisper-timestamped; extra == "whisper"
20
- Dynamic: license-file
21
-
22
- # Cutted
23
- AI-powered audio editor controllable via natural language
24
-
25
- Note: This app is currently not functional.
26
-
27
- # Installation
28
-
29
- Install dependencies:
30
-
31
- **Debian:**
32
- ```bash
33
- sudo apt update
34
- sudo apt install ffmpeg git
35
- ```
36
-
37
- **Arch Linux:**
38
- ```bash
39
- sudo pacman -Syu ffmpeg git
40
- ```
41
-
42
- Clone the repository:
43
-
44
- ```bash
45
- git clone https://github.com/simon0302010/Cutted.git
46
- cd Cutted
47
- ```
48
-
49
- Create a virtual environment:
50
-
51
- ```bash
52
- python -m venv venv
53
- source venv/bin/activate
54
- ```
55
-
56
- Install the package:
57
-
58
- ```bash
59
- pip install .
60
- ```
61
-
62
- # Usage
63
-
64
- Run the package:
65
-
66
- ```bash
67
- python -m cutted
68
- ```
@@ -1,12 +0,0 @@
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,,
File without changes