Compare commits
No commits in common. "8fc9c9247dc4bcfaeb7ae8d83d165748a1032894" and "2f884fb7dee09dc6b65427cde30c9eae3509c0a0" have entirely different histories.
8fc9c9247d
...
2f884fb7de
2 changed files with 2 additions and 54 deletions
|
|
@ -22,8 +22,5 @@ requires `~/.config/simplewhispr/config.json`:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## integrations
|
|
||||||
waybar: `tail -F /tmp/simplewhispr-waybar.log`, json output
|
|
||||||
|
|
||||||
---
|
---
|
||||||
Copyright (C) Noah Swerhun under the terms of [GNU GPLv3](https://www.gnu.org/licenses/gpl-3.0-standalone.html).
|
Copyright (C) Noah Swerhun under the terms of [GNU GPLv3](https://www.gnu.org/licenses/gpl-3.0-standalone.html).
|
||||||
|
|
|
||||||
53
main.py
53
main.py
|
|
@ -10,7 +10,6 @@ from openai import OpenAI
|
||||||
|
|
||||||
# flag to control recording
|
# flag to control recording
|
||||||
recording = True
|
recording = True
|
||||||
status_file = None
|
|
||||||
|
|
||||||
|
|
||||||
def parse_config() -> tuple[str, str]:
|
def parse_config() -> tuple[str, str]:
|
||||||
|
|
@ -34,21 +33,6 @@ def parse_config() -> tuple[str, str]:
|
||||||
raise Exception(f"fatal: configuration error: {e}")
|
raise Exception(f"fatal: configuration error: {e}")
|
||||||
|
|
||||||
|
|
||||||
def report_status(message: str):
|
|
||||||
global status_file
|
|
||||||
if status_file is None:
|
|
||||||
try:
|
|
||||||
status_file = open("/tmp/simplewhispr-waybar.log", "w")
|
|
||||||
except OSError:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
status_file.write(f'{{"text":"{message}"}}\n')
|
|
||||||
status_file.flush()
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def handle_sigusr1(signum, frame):
|
def handle_sigusr1(signum, frame):
|
||||||
global recording
|
global recording
|
||||||
print("\ninfo: SIGUSR1 received. stopping recording.")
|
print("\ninfo: SIGUSR1 received. stopping recording.")
|
||||||
|
|
@ -72,26 +56,6 @@ def transcribe_audio(filename: str) -> str:
|
||||||
return transcription.text
|
return transcription.text
|
||||||
|
|
||||||
|
|
||||||
def cleanup_text(text: str) -> str:
|
|
||||||
api_key, _ = parse_config()
|
|
||||||
client = OpenAI(api_key=api_key)
|
|
||||||
|
|
||||||
response = client.chat.completions.create(
|
|
||||||
model="gpt-5.4-nano",
|
|
||||||
messages=[
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "IMPORTANT: your job is to clean up dictated text. you will remove filler words and correct punctuation and grammar. your goal should be to change as few of the meaningful words as possible, while removing words that are not meaningful. WARNING: do not change the phrasing or edit for clarity or style, simply remove filler words and clean up grammar.",
|
|
||||||
},
|
|
||||||
{"role": "user", "content": text},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
res = response.choices[0].message.content
|
|
||||||
if res is None:
|
|
||||||
raise Exception("cleanup gave no output")
|
|
||||||
return res.strip()
|
|
||||||
|
|
||||||
|
|
||||||
def grab_recording() -> str:
|
def grab_recording() -> str:
|
||||||
output_filename = "/tmp/simplewhispr-recording.wav"
|
output_filename = "/tmp/simplewhispr-recording.wav"
|
||||||
# start ffmpeg recording
|
# start ffmpeg recording
|
||||||
|
|
@ -100,7 +64,6 @@ def grab_recording() -> str:
|
||||||
print(
|
print(
|
||||||
f"info: starting recording to {output_filename}. send SIGUSR1 (kill -usr1 {os.getpid()}) to stop."
|
f"info: starting recording to {output_filename}. send SIGUSR1 (kill -usr1 {os.getpid()}) to stop."
|
||||||
)
|
)
|
||||||
report_status("")
|
|
||||||
|
|
||||||
process = subprocess.Popen(
|
process = subprocess.Popen(
|
||||||
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True
|
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True
|
||||||
|
|
@ -111,14 +74,12 @@ def grab_recording() -> str:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
if process.poll() is not None:
|
if process.poll() is not None:
|
||||||
print("fatal: ffmpeg exited unexpectedly.")
|
print("fatal: ffmpeg exited unexpectedly.")
|
||||||
report_status("")
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# stop recording
|
# stop recording
|
||||||
process.terminate()
|
process.terminate()
|
||||||
process.wait()
|
process.wait()
|
||||||
print("info: recording stopped.")
|
print("info: recording stopped.")
|
||||||
report_status("")
|
|
||||||
return output_filename
|
return output_filename
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -126,23 +87,13 @@ def main():
|
||||||
with open("/tmp/simplewhispr.pid", "w") as f:
|
with open("/tmp/simplewhispr.pid", "w") as f:
|
||||||
f.write(str(os.getpid()))
|
f.write(str(os.getpid()))
|
||||||
|
|
||||||
report_status("")
|
|
||||||
|
|
||||||
recording_file = grab_recording()
|
recording_file = grab_recording()
|
||||||
|
|
||||||
report_status("")
|
|
||||||
print("info: transcribing...")
|
print("info: transcribing...")
|
||||||
transcription = transcribe_audio(recording_file)
|
transcription = transcribe_audio(recording_file)
|
||||||
print(f"info: raw transcription: {transcription}")
|
print(f"info: transcription: {transcription}")
|
||||||
|
|
||||||
print("info: cleaning up...")
|
|
||||||
cleaned_transcription = cleanup_text(transcription)
|
|
||||||
print(f"info: cleaned transcription: {cleaned_transcription}")
|
|
||||||
|
|
||||||
# use wtype to type the output
|
# use wtype to type the output
|
||||||
report_status("")
|
subprocess.run(["wtype", transcription])
|
||||||
subprocess.run(["wtype", cleaned_transcription])
|
|
||||||
report_status("")
|
|
||||||
|
|
||||||
if os.path.exists("/tmp/simplewhispr.pid"):
|
if os.path.exists("/tmp/simplewhispr.pid"):
|
||||||
os.remove("/tmp/simplewhispr.pid")
|
os.remove("/tmp/simplewhispr.pid")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue