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 +1 -1
- cutted/app.py +39 -27
- cutted/core/audio_processor.py +10 -3
- cutted/core/gemini.py +13 -4
- cutted-0.3.2.dist-info/METADATA +55 -0
- cutted-0.3.2.dist-info/RECORD +12 -0
- cutted-0.3.1.dist-info/METADATA +0 -68
- cutted-0.3.1.dist-info/RECORD +0 -12
- {cutted-0.3.1.dist-info → cutted-0.3.2.dist-info}/WHEEL +0 -0
- {cutted-0.3.1.dist-info → cutted-0.3.2.dist-info}/licenses/LICENSE +0 -0
- {cutted-0.3.1.dist-info → cutted-0.3.2.dist-info}/top_level.txt +0 -0
cutted/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
__version__ = "0.3.
|
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="
|
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
|
-
|
187
|
-
|
188
|
-
if
|
189
|
-
if
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
if
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
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:
|
cutted/core/audio_processor.py
CHANGED
@@ -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
|
+

|
23
|
+

|
24
|
+

|
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,,
|
cutted-0.3.1.dist-info/METADATA
DELETED
@@ -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
|
-
```
|
cutted-0.3.1.dist-info/RECORD
DELETED
@@ -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
|
File without changes
|
File without changes
|