meeting-noter 0.3.0__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.

Potentially problematic release.


This version of meeting-noter might be problematic. Click here for more details.

Files changed (38) hide show
  1. meeting_noter/__init__.py +3 -0
  2. meeting_noter/__main__.py +6 -0
  3. meeting_noter/audio/__init__.py +1 -0
  4. meeting_noter/audio/capture.py +209 -0
  5. meeting_noter/audio/encoder.py +176 -0
  6. meeting_noter/audio/system_audio.py +363 -0
  7. meeting_noter/cli.py +308 -0
  8. meeting_noter/config.py +197 -0
  9. meeting_noter/daemon.py +514 -0
  10. meeting_noter/gui/__init__.py +5 -0
  11. meeting_noter/gui/__main__.py +6 -0
  12. meeting_noter/gui/app.py +53 -0
  13. meeting_noter/gui/main_window.py +50 -0
  14. meeting_noter/gui/meetings_tab.py +348 -0
  15. meeting_noter/gui/recording_tab.py +358 -0
  16. meeting_noter/gui/settings_tab.py +249 -0
  17. meeting_noter/install/__init__.py +1 -0
  18. meeting_noter/install/macos.py +102 -0
  19. meeting_noter/meeting_detector.py +296 -0
  20. meeting_noter/menubar.py +432 -0
  21. meeting_noter/output/__init__.py +1 -0
  22. meeting_noter/output/writer.py +96 -0
  23. meeting_noter/resources/__init__.py +1 -0
  24. meeting_noter/resources/icon.icns +0 -0
  25. meeting_noter/resources/icon.png +0 -0
  26. meeting_noter/resources/icon_128.png +0 -0
  27. meeting_noter/resources/icon_16.png +0 -0
  28. meeting_noter/resources/icon_256.png +0 -0
  29. meeting_noter/resources/icon_32.png +0 -0
  30. meeting_noter/resources/icon_512.png +0 -0
  31. meeting_noter/resources/icon_64.png +0 -0
  32. meeting_noter/transcription/__init__.py +1 -0
  33. meeting_noter/transcription/engine.py +208 -0
  34. meeting_noter-0.3.0.dist-info/METADATA +261 -0
  35. meeting_noter-0.3.0.dist-info/RECORD +38 -0
  36. meeting_noter-0.3.0.dist-info/WHEEL +5 -0
  37. meeting_noter-0.3.0.dist-info/entry_points.txt +2 -0
  38. meeting_noter-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,208 @@
1
+ """Transcription engine using faster-whisper."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import click
6
+ from pathlib import Path
7
+ from datetime import datetime
8
+ from typing import Optional
9
+
10
+
11
+ def get_model(model_size: str = "tiny.en"):
12
+ """Load the Whisper model.
13
+
14
+ Models are cached after first download (~75MB for tiny.en).
15
+ """
16
+ from faster_whisper import WhisperModel
17
+
18
+ click.echo(f"Loading model '{model_size}'...")
19
+
20
+ # Use INT8 for CPU efficiency
21
+ model = WhisperModel(
22
+ model_size,
23
+ device="cpu",
24
+ compute_type="int8",
25
+ )
26
+
27
+ return model
28
+
29
+
30
+ def format_timestamp(seconds: float) -> str:
31
+ """Format seconds as [HH:MM:SS] or [MM:SS]."""
32
+ hours = int(seconds // 3600)
33
+ minutes = int((seconds % 3600) // 60)
34
+ secs = int(seconds % 60)
35
+
36
+ if hours > 0:
37
+ return f"[{hours:02d}:{minutes:02d}:{secs:02d}]"
38
+ return f"[{minutes:02d}:{secs:02d}]"
39
+
40
+
41
+ def transcribe_audio(audio_path: Path, model_size: str = "tiny.en") -> str:
42
+ """Transcribe an audio file.
43
+
44
+ Args:
45
+ audio_path: Path to MP3 or WAV file
46
+ model_size: Whisper model to use
47
+
48
+ Returns:
49
+ Formatted transcript string
50
+ """
51
+ model = get_model(model_size)
52
+
53
+ click.echo(f"Transcribing {audio_path.name}...")
54
+
55
+ segments, info = model.transcribe(
56
+ str(audio_path),
57
+ beam_size=5,
58
+ vad_filter=True, # Voice Activity Detection
59
+ vad_parameters=dict(
60
+ min_silence_duration_ms=500,
61
+ ),
62
+ )
63
+
64
+ # Build transcript
65
+ lines = []
66
+ lines.append("Meeting Transcription")
67
+ lines.append(f"File: {audio_path.name}")
68
+ lines.append(f"Transcribed: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
69
+ lines.append(f"Language: {info.language} (probability: {info.language_probability:.2f})")
70
+ lines.append(f"Duration: {info.duration:.1f} seconds")
71
+ lines.append("-" * 40)
72
+ lines.append("")
73
+
74
+ for segment in segments:
75
+ timestamp = format_timestamp(segment.start)
76
+ text = segment.text.strip()
77
+ if text:
78
+ lines.append(f"{timestamp} {text}")
79
+
80
+ return "\n".join(lines)
81
+
82
+
83
+ def transcribe_file(
84
+ file: Optional[str],
85
+ output_dir: Path,
86
+ model_size: str = "tiny.en",
87
+ transcripts_dir: Optional[Path] = None,
88
+ ):
89
+ """Transcribe a recording file.
90
+
91
+ If no file specified, transcribes the most recent recording.
92
+ Saves transcript to transcripts_dir (defaults to same as audio file).
93
+ """
94
+ # Find the file to transcribe
95
+ if file:
96
+ audio_path = Path(file)
97
+ if not audio_path.exists():
98
+ # Try in output dir
99
+ audio_path = output_dir / file
100
+ if not audio_path.exists():
101
+ click.echo(click.style(f"File not found: {file}", fg="red"))
102
+ return
103
+ else:
104
+ # Find most recent recording
105
+ mp3_files = sorted(output_dir.glob("*.mp3"), key=lambda p: p.stat().st_mtime)
106
+ if not mp3_files:
107
+ click.echo(click.style(
108
+ f"No recordings found in {output_dir}",
109
+ fg="yellow"
110
+ ))
111
+ return
112
+ audio_path = mp3_files[-1]
113
+ click.echo(f"Using most recent recording: {audio_path.name}")
114
+
115
+ # Determine transcript path
116
+ if transcripts_dir:
117
+ transcripts_dir.mkdir(parents=True, exist_ok=True)
118
+ transcript_path = transcripts_dir / audio_path.with_suffix(".txt").name
119
+ else:
120
+ transcript_path = audio_path.with_suffix(".txt")
121
+ if transcript_path.exists():
122
+ click.echo(click.style(
123
+ f"Transcript already exists: {transcript_path.name}",
124
+ fg="yellow"
125
+ ))
126
+ if not click.confirm("Overwrite?"):
127
+ return
128
+
129
+ # Transcribe
130
+ try:
131
+ transcript = transcribe_audio(audio_path, model_size)
132
+
133
+ # Save transcript
134
+ transcript_path.write_text(transcript)
135
+ click.echo(click.style(
136
+ f"\nTranscript saved: {transcript_path}",
137
+ fg="green"
138
+ ))
139
+
140
+ # Show preview
141
+ click.echo("\n--- Preview ---")
142
+ lines = transcript.split("\n")
143
+ preview_lines = lines[:15]
144
+ for line in preview_lines:
145
+ click.echo(line)
146
+ if len(lines) > 15:
147
+ click.echo(f"... ({len(lines) - 15} more lines)")
148
+
149
+ except Exception as e:
150
+ click.echo(click.style(f"Transcription failed: {e}", fg="red"))
151
+ raise
152
+
153
+
154
+ def transcribe_live(output_dir: Path, model_size: str = "tiny.en"):
155
+ """Real-time transcription of ongoing recording.
156
+
157
+ Note: This is more CPU intensive and may have latency.
158
+ """
159
+ click.echo(click.style(
160
+ "Live transcription is experimental and CPU-intensive.",
161
+ fg="yellow"
162
+ ))
163
+
164
+ # Find active recording (most recent, still being written)
165
+ mp3_files = sorted(output_dir.glob("*.mp3"), key=lambda p: p.stat().st_mtime)
166
+ if not mp3_files:
167
+ click.echo("No recordings found. Is the daemon running?")
168
+ return
169
+
170
+ latest = mp3_files[-1]
171
+ click.echo(f"Monitoring: {latest.name}")
172
+ click.echo("Press Ctrl+C to stop.\n")
173
+
174
+ model = get_model(model_size)
175
+ last_position = 0
176
+
177
+ try:
178
+ import time
179
+ while True:
180
+ # Check file size
181
+ current_size = latest.stat().st_size
182
+ if current_size > last_position:
183
+ # New data available - transcribe the whole file
184
+ # (faster-whisper doesn't support streaming well)
185
+ try:
186
+ segments, info = model.transcribe(
187
+ str(latest),
188
+ beam_size=3, # Faster for live
189
+ vad_filter=True,
190
+ )
191
+
192
+ # Print new segments
193
+ for segment in segments:
194
+ if segment.end > last_position / 1000: # Rough estimate
195
+ timestamp = format_timestamp(segment.start)
196
+ text = segment.text.strip()
197
+ if text:
198
+ click.echo(f"{timestamp} {text}")
199
+
200
+ last_position = current_size
201
+ except Exception as e:
202
+ # File might be locked, retry
203
+ pass
204
+
205
+ time.sleep(5) # Check every 5 seconds
206
+
207
+ except KeyboardInterrupt:
208
+ click.echo("\nStopped live transcription.")
@@ -0,0 +1,261 @@
1
+ Metadata-Version: 2.4
2
+ Name: meeting-noter
3
+ Version: 0.3.0
4
+ Summary: Offline meeting transcription for macOS with automatic meeting detection
5
+ Author: Victor
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/tech4vision/meeting-noter
8
+ Project-URL: Repository, https://github.com/tech4vision/meeting-noter
9
+ Project-URL: Issues, https://github.com/tech4vision/meeting-noter/issues
10
+ Keywords: meeting,transcription,whisper,offline,speech-to-text,audio
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: click>=8.0
25
+ Requires-Dist: sounddevice>=0.4.6
26
+ Requires-Dist: numpy>=1.21
27
+ Requires-Dist: faster-whisper>=1.0.0
28
+ Requires-Dist: lameenc>=1.5.0
29
+ Requires-Dist: rumps>=0.4.0
30
+ Requires-Dist: PyQt6>=6.5.0
31
+ Requires-Dist: pyobjc-framework-Cocoa>=9.0; sys_platform == "darwin"
32
+ Requires-Dist: pyobjc-framework-Quartz>=9.0; sys_platform == "darwin"
33
+ Requires-Dist: pyobjc-framework-ScreenCaptureKit>=9.0; sys_platform == "darwin"
34
+ Requires-Dist: pyobjc-framework-AVFoundation>=9.0; sys_platform == "darwin"
35
+ Requires-Dist: pyobjc-framework-CoreMedia>=9.0; sys_platform == "darwin"
36
+ Requires-Dist: pyobjc-framework-libdispatch>=9.0; sys_platform == "darwin"
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest>=7.0; extra == "dev"
39
+ Requires-Dist: pytest-cov; extra == "dev"
40
+ Requires-Dist: black; extra == "dev"
41
+ Requires-Dist: ruff; extra == "dev"
42
+ Requires-Dist: mypy; extra == "dev"
43
+
44
+ # Meeting Noter
45
+
46
+ Offline meeting transcription tool for macOS. Captures both your voice and meeting participants' audio, saves to MP3, and transcribes locally using Whisper.
47
+
48
+ ## Features
49
+
50
+ - **No virtual audio devices needed** - Uses ScreenCaptureKit (like Notion, Discord)
51
+ - **Captures both sides** - Your mic + system audio (meeting participants)
52
+ - **Offline transcription** - Uses Whisper locally, no API calls
53
+ - **Auto-detection** - Detects active meetings (Zoom, Teams, Meet, Slack)
54
+ - **Multiple interfaces** - Menu bar app, desktop GUI, or CLI
55
+ - **Auto-segmentation** - One file per meeting (detects silence)
56
+
57
+ ## Installation
58
+
59
+ ### Option 1: Using pipx (Recommended)
60
+
61
+ ```bash
62
+ # Install pipx if you don't have it
63
+ brew install pipx
64
+ pipx ensurepath
65
+
66
+ # Install meeting-noter
67
+ cd /path/to/meeting-noter
68
+ pipx install -e .
69
+ ```
70
+
71
+ ### Option 2: Using a virtual environment
72
+
73
+ ```bash
74
+ cd /path/to/meeting-noter
75
+ python3 -m venv .venv
76
+ .venv/bin/pip install --upgrade pip
77
+ .venv/bin/pip install -e .
78
+ ```
79
+
80
+ Then add an alias in your `~/.zshrc`:
81
+
82
+ ```bash
83
+ echo 'alias meeting-noter="/path/to/meeting-noter/.venv/bin/meeting-noter"' >> ~/.zshrc
84
+ source ~/.zshrc
85
+ ```
86
+
87
+ ## Quick Start
88
+
89
+ ### 1. One-time Setup
90
+
91
+ ```bash
92
+ meeting-noter setup
93
+ ```
94
+
95
+ This will request Screen Recording permission, which is needed to capture meeting participants' audio.
96
+
97
+ ### 2. Launch the App
98
+
99
+ **Menu Bar App** (recommended):
100
+ ```bash
101
+ meeting-noter menubar
102
+ ```
103
+
104
+ **Desktop GUI**:
105
+ ```bash
106
+ meeting-noter gui
107
+ ```
108
+
109
+ **CLI Recording**:
110
+ ```bash
111
+ meeting-noter start "Weekly Standup"
112
+ ```
113
+
114
+ ### 3. Record a Meeting
115
+
116
+ - The menu bar app auto-detects meetings and prompts to record
117
+ - Or manually start recording via the GUI/CLI
118
+ - Press Ctrl+C (CLI) or click Stop to end recording
119
+
120
+ ### 4. Transcribe
121
+
122
+ Recordings are auto-transcribed by default. Or manually:
123
+
124
+ ```bash
125
+ # Transcribe the most recent recording
126
+ meeting-noter transcribe
127
+
128
+ # Transcribe a specific file
129
+ meeting-noter transcribe recording.mp3
130
+
131
+ # List all recordings
132
+ meeting-noter list
133
+ ```
134
+
135
+ ## Commands
136
+
137
+ | Command | Description |
138
+ |---------|-------------|
139
+ | `meeting-noter setup` | One-time setup (Screen Recording permission) |
140
+ | `meeting-noter menubar` | Launch menu bar app |
141
+ | `meeting-noter gui` | Launch desktop GUI |
142
+ | `meeting-noter start [name]` | Interactive CLI recording |
143
+ | `meeting-noter daemon` | Start background audio capture |
144
+ | `meeting-noter status` | Check daemon status |
145
+ | `meeting-noter stop` | Stop the daemon |
146
+ | `meeting-noter list` | List recent recordings |
147
+ | `meeting-noter transcribe` | Transcribe a recording |
148
+ | `meeting-noter devices` | List audio devices |
149
+
150
+ ## Options
151
+
152
+ ### `start`
153
+ - First argument: Meeting name (optional, auto-generates timestamp if omitted)
154
+
155
+ ### `daemon`
156
+ - `-o, --output-dir`: Where to save recordings (default: `~/meetings`)
157
+ - `-f, --foreground`: Run in foreground instead of background
158
+ - `-n, --name`: Meeting name for the recording
159
+
160
+ ### `transcribe`
161
+ - `-m, --model`: Whisper model size (tiny.en, base.en, small.en, medium.en, large-v3)
162
+ - `-l, --live`: Real-time transcription (experimental)
163
+ - `-o, --output-dir`: Directory with recordings
164
+
165
+ ### `list`
166
+ - `-n, --limit`: Number of recordings to show
167
+ - `-o, --output-dir`: Directory with recordings
168
+
169
+ ## How It Works
170
+
171
+ ```
172
+ ┌─────────────────────────────────────┐
173
+ │ Your Meeting App │
174
+ │ (Zoom/Teams/Meet/Slack) │
175
+ └──────────────────┬──────────────────┘
176
+
177
+ ┌─────────────┴─────────────┐
178
+ ▼ ▼
179
+ ┌─────────┐ ┌─────────────┐
180
+ │ Mic │ │ System Audio│
181
+ │(default)│ │(ScreenCaptureKit)
182
+ └────┬────┘ └──────┬──────┘
183
+ │ │
184
+ └───────────┬───────────────┘
185
+
186
+ ┌─────────────┐
187
+ │Meeting Noter│
188
+ │ (capture) │
189
+ └──────┬──────┘
190
+
191
+
192
+ ~/meetings/2024-01-15_Weekly_Standup.mp3
193
+
194
+ ▼ (auto or on-demand)
195
+ ┌─────────────┐
196
+ │ Whisper │ (local)
197
+ └──────┬──────┘
198
+
199
+
200
+ ~/meetings/2024-01-15_Weekly_Standup.txt
201
+ ```
202
+
203
+ ## Permissions Required
204
+
205
+ 1. **Microphone** - For capturing your voice
206
+ 2. **Screen Recording** - For capturing system audio (meeting participants)
207
+ - Grant in: System Settings > Privacy & Security > Screen Recording
208
+ - This uses ScreenCaptureKit, the same API used by Notion, Discord, etc.
209
+
210
+ ## Troubleshooting
211
+
212
+ ### No system audio captured (only my voice)
213
+
214
+ Screen Recording permission not granted. Go to:
215
+ System Settings > Privacy & Security > Screen Recording
216
+
217
+ Enable the toggle for Terminal (or your IDE/app).
218
+
219
+ ### Meeting not auto-detected
220
+
221
+ Meeting detection works for: Zoom, Microsoft Teams, Google Meet, Slack.
222
+ The meeting window must be open (not minimized).
223
+
224
+ ### Transcription is slow
225
+
226
+ Use a smaller model:
227
+
228
+ ```bash
229
+ meeting-noter transcribe --model tiny.en
230
+ ```
231
+
232
+ Model sizes:
233
+ - `tiny.en` (~75MB) - Fastest, good for most cases
234
+ - `base.en` (~150MB) - Better accuracy
235
+ - `small.en` (~500MB) - High accuracy
236
+ - `medium.en` (~1.5GB) - Very high accuracy
237
+ - `large-v3` (~3GB) - Best accuracy
238
+
239
+ ## Configuration
240
+
241
+ Config file: `~/.config/meeting-noter/config.json`
242
+
243
+ ```json
244
+ {
245
+ "recordings_dir": "~/meetings",
246
+ "transcripts_dir": "~/meetings",
247
+ "whisper_model": "tiny.en",
248
+ "auto_transcribe": true,
249
+ "silence_timeout": 5,
250
+ "capture_system_audio": true
251
+ }
252
+ ```
253
+
254
+ ## Requirements
255
+
256
+ - macOS 12.3+ (for ScreenCaptureKit)
257
+ - Python 3.9+
258
+
259
+ ## License
260
+
261
+ MIT
@@ -0,0 +1,38 @@
1
+ meeting_noter/__init__.py,sha256=bLOErRC3sfnQ4a4RyZUzUljZEikXy7zOiYYUz5GytPg,103
2
+ meeting_noter/__main__.py,sha256=6sSOqH1o3jvgvkVzsVKmF6-xVGcUAbNVQkRl2CrygdE,120
3
+ meeting_noter/cli.py,sha256=w4cBrvg58inkgbApK_z90csBfb4HWBuXveLdD3J1bc0,8540
4
+ meeting_noter/config.py,sha256=41LFBNp5o0IojYS5Hf0FJVIr7GNn7B5O1TJDE8SQkkk,5977
5
+ meeting_noter/daemon.py,sha256=o7U11WmdoKG58SLs70-vzS64kkjMTY5qN0F0bs0eApk,16239
6
+ meeting_noter/meeting_detector.py,sha256=I8zzSdSSmbfd3yyCOyzPL8AS-xSHttFCagrDE35qcho,9412
7
+ meeting_noter/menubar.py,sha256=Wmwaw-_f2Zky6-0DLC5Ql2o6_VBG1-sWacL85dNeGwU,15366
8
+ meeting_noter/audio/__init__.py,sha256=O7PU8CxHSHxMeHbc9Jdwt9kePLQzsPh81GQU7VHCtBY,44
9
+ meeting_noter/audio/capture.py,sha256=fDrT5oXfva8vdFlht9cv60NviKbksw2QeJ8eOtI19uE,6469
10
+ meeting_noter/audio/encoder.py,sha256=UT9yLbURsRfVafRbT-DRianSCx1fOEwWPLP-LULYqVo,5443
11
+ meeting_noter/audio/system_audio.py,sha256=jbHGjNCerI19weXap0a90Ik17lVTCT1hCEgRKYke-p8,13016
12
+ meeting_noter/gui/__init__.py,sha256=z5GxxaeXyjqyEa9ox0dQxuL5u_BART0bi7cI6rfntEI,103
13
+ meeting_noter/gui/__main__.py,sha256=A2HWdYod0bTgjQQIi21O7XpmgxLH36e_X0aygEUZLls,146
14
+ meeting_noter/gui/app.py,sha256=COUAWu_dR5HriNYxbE86CVGS1eGYqyteH2oUFN_YtYQ,1370
15
+ meeting_noter/gui/main_window.py,sha256=vSvNO86CHMgJf9Pem8AOdrqKyTV9ITp3W4nCoqIuAmI,1667
16
+ meeting_noter/gui/meetings_tab.py,sha256=pqXqMv5YvCj8H6yR_TF3SMzsIDMAxyLe2otbENbM2SY,12315
17
+ meeting_noter/gui/recording_tab.py,sha256=UlrPkUiOmkGgOKqVrfAVp4EyiY5sq86W49Y-YAhYexY,12521
18
+ meeting_noter/gui/settings_tab.py,sha256=NUQVKDdSpyNp_MVxPLw2dB93wxaD5VeBKiDtGS4CyoU,8446
19
+ meeting_noter/install/__init__.py,sha256=SX5vLFMrV8aBDEGW18jhaqBqJqnRXaeo0Ct7QVGDgvE,38
20
+ meeting_noter/install/macos.py,sha256=dO-86zbNKRtt0l4D8naVn7kFWjzI8TufWLWE3FRLHQ8,3400
21
+ meeting_noter/output/__init__.py,sha256=F7xPlOrqweZcPbZtDrhved1stBI59vnWnLYfGwdu6oY,31
22
+ meeting_noter/output/writer.py,sha256=zO8y6FAFUAp0EEtALY-M5e2Ja5P-hgV38JjcKW7c-bA,3017
23
+ meeting_noter/resources/__init__.py,sha256=yzHNxgypkuVDFZWv6xZjUygOVB_Equ9NNX_HGRvN7VM,43
24
+ meeting_noter/resources/icon.icns,sha256=zMWqXCq7pI5acS0tbekFgFDvLt66EKUBP5-5IgztwPM,35146
25
+ meeting_noter/resources/icon.png,sha256=nK0hM6CPMor_xXRFYURpm0muA2O7yzotyydUQx-ukyg,2390
26
+ meeting_noter/resources/icon_128.png,sha256=Wg27dIpFfMzv15HG6eQpSqg72jrbGBcqLkGjOfAptO4,1169
27
+ meeting_noter/resources/icon_16.png,sha256=GONIIZCP9FUMb_MWZWMz1_iWxsPCPOwW_XcrPF7W8KY,215
28
+ meeting_noter/resources/icon_256.png,sha256=nK0hM6CPMor_xXRFYURpm0muA2O7yzotyydUQx-ukyg,2390
29
+ meeting_noter/resources/icon_32.png,sha256=Bw6hJXqkd-d1OfDpFv2om7Stex7daedxnpXt32xR8Sg,344
30
+ meeting_noter/resources/icon_512.png,sha256=o7X3ngYcppcIAAk9AcfPx94MUmrsPRp0qBTpb9SzfX8,5369
31
+ meeting_noter/resources/icon_64.png,sha256=TqG7Awx3kK8YdiX1e_z1odZonosZyQI2trlkNZCzUoI,607
32
+ meeting_noter/transcription/__init__.py,sha256=7GY9diP06DzFyoli41wddbrPv5bVDzH35bmnWlIJev4,29
33
+ meeting_noter/transcription/engine.py,sha256=HK2J2QOBNIDm1MXW-gkagXP8C8cqUfK_WylHQD_LqOI,6320
34
+ meeting_noter-0.3.0.dist-info/METADATA,sha256=FhIlKw7Wg1tRRLsFBmrXkKLa8zf3L2csAtO1bQADbcQ,7952
35
+ meeting_noter-0.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
36
+ meeting_noter-0.3.0.dist-info/entry_points.txt,sha256=rKNhzjSF5-e3bLRr8LVe22FeiwcacXabCvNpoEXfu4I,56
37
+ meeting_noter-0.3.0.dist-info/top_level.txt,sha256=9Tuq04_0SXM0OXOHVbOHkHkB5tG3fqkrMrfzCMpbLpY,14
38
+ meeting_noter-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ meeting-noter = meeting_noter.cli:cli
@@ -0,0 +1 @@
1
+ meeting_noter