summaryrefslogtreecommitdiff
path: root/src/parley/cli.py
blob: 735d53235d17f61e7252778224764941e4e05ac7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Standalone terminal frontend for the shared Parley core."""

import sys
import tempfile
import termios
import tty
from pathlib import Path

from .config import Config
from .errors import ParleyError
from .persistence import save_transcript
from .recording import Recorder
from .transcription import Transcriber


def wait_for_stop() -> bool:
    """Wait for Enter/Escape and return True when cancellation was requested."""
    if not sys.stdin.isatty():
        return input() == "\x1b"
    descriptor = sys.stdin.fileno()
    previous_settings = termios.tcgetattr(descriptor)
    try:
        tty.setcbreak(descriptor)
        while True:
            key = sys.stdin.read(1)
            if key in ("\r", "\n", ""):
                return False
            if key == "\x1b":
                return True
    finally:
        termios.tcsetattr(descriptor, termios.TCSADRAIN, previous_settings)


def run_once(config: Config) -> tuple[str, Path]:
    config.validate()
    recorder = Recorder(config)
    with tempfile.TemporaryDirectory(prefix="parley-") as temporary:
        workspace = Path(temporary)
        recorder.start(workspace / "recording.wav")
        print(
            "Recording; press Enter to transcribe or Escape to cancel.",
            file=sys.stderr,
            flush=True,
        )
        try:
            cancelled = wait_for_stop()
        except BaseException:
            recorder.cancel()
            raise
        if cancelled:
            recorder.cancel()
            raise KeyboardInterrupt
        wav_path = recorder.stop()
        transcript = Transcriber(config).transcribe(wav_path, workspace)
        path = save_transcript(transcript, config.transcript_dir)
        return transcript, path


def main() -> int:
    try:
        transcript, path = run_once(Config.from_environment())
        print(transcript)
        print(f"Saved to {path}", file=sys.stderr)
        return 0
    except KeyboardInterrupt:
        print("Cancelled.", file=sys.stderr)
        return 130
    except (OSError, ParleyError) as error:
        print(f"error: {error}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())