()
| 79 | |
| 80 | |
| 81 | def main(): |
| 82 | p = argparse.ArgumentParser( |
| 83 | prog="funasr", |
| 84 | description="FunASR - speech recognition CLI. 50+ languages, speaker diarization.", |
| 85 | epilog="Examples:\n" |
| 86 | " funasr audio.wav\n" |
| 87 | " funasr audio.wav --model sensevoice -f json\n" |
| 88 | " funasr audio.wav -f srt -o ./subs\n" |
| 89 | " funasr audio.wav --spk --timestamps\n", |
| 90 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 91 | ) |
| 92 | p.add_argument("audio", nargs="+", help="Audio file(s) to transcribe") |
| 93 | p.add_argument("--model", "-m", default="sensevoice", choices=list(MODEL_CONFIGS), help="Model (default: sensevoice)") |
| 94 | p.add_argument("--language", "-l", default=None, help="Language: zh, en, ja, ko, yue, auto") |
| 95 | p.add_argument("--device", default=None, help="Device: cuda:0, cpu (default: auto)") |
| 96 | p.add_argument("--output-format", "-f", default="text", choices=["text", "json", "srt", "tsv"], help="Output format (default: text)") |
| 97 | p.add_argument("--output-dir", "-o", default=None, help="Write output files to directory") |
| 98 | p.add_argument("--timestamps", action="store_true", help="Include word-level timestamps") |
| 99 | p.add_argument("--spk", action="store_true", help="Enable speaker diarization") |
| 100 | p.add_argument("--hotwords", default=None, help="Comma-separated hotwords") |
| 101 | p.add_argument("--verbose", "-v", action="store_true", help="Show loading/timing info on stderr") |
| 102 | p.add_argument("--version", action="version", version=f"%(prog)s {_get_version()}") |
| 103 | args = p.parse_args() |
| 104 | |
| 105 | if args.verbose: |
| 106 | print(f"Loading model: {args.model} ...", file=sys.stderr) |
| 107 | |
| 108 | import torch |
| 109 | from funasr import AutoModel |
| 110 | |
| 111 | device = args.device or ("cuda:0" if torch.cuda.is_available() else "cpu") |
| 112 | config = MODEL_CONFIGS[args.model].copy() |
| 113 | if args.spk and "spk_model" not in config: |
| 114 | config["spk_model"] = "cam++" |
| 115 | if "punc_model" not in config and args.model not in ("fun-asr-nano", "sensevoice"): |
| 116 | config["punc_model"] = "ct-punc" |
| 117 | |
| 118 | t_load = time.time() |
| 119 | model = AutoModel(device=device, disable_update=True, **config) |
| 120 | if args.verbose: |
| 121 | print(f"Model loaded in {time.time() - t_load:.1f}s", file=sys.stderr) |
| 122 | |
| 123 | if args.output_dir: |
| 124 | os.makedirs(args.output_dir, exist_ok=True) |
| 125 | |
| 126 | for audio_path in args.audio: |
| 127 | if not os.path.isfile(audio_path): |
| 128 | print(f"Error: file not found: {audio_path}", file=sys.stderr) |
| 129 | sys.exit(1) |
| 130 | |
| 131 | if args.verbose: |
| 132 | print(f"Transcribing: {audio_path}", file=sys.stderr) |
| 133 | |
| 134 | t0 = time.time() |
| 135 | gen_kw = {"input": audio_path, "batch_size": 1} |
| 136 | if args.language: |
| 137 | gen_kw["language"] = args.language |
| 138 | if args.hotwords: |
no test coverage detected
searching dependent graphs…