main.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/gordonklaus/portaudio"
  6. sherpa "github.com/k2-fsa/sherpa-ncnn-go/sherpa_ncnn"
  7. flag "github.com/spf13/pflag"
  8. "log"
  9. "os"
  10. "strings"
  11. )
  12. func main() {
  13. err := portaudio.Initialize()
  14. if err != nil {
  15. log.Fatalf("Unable to initialize portaudio: %v\n", err)
  16. }
  17. defer portaudio.Terminate()
  18. default_device, err := portaudio.DefaultInputDevice()
  19. if err != nil {
  20. log.Fatal("Failed to get default input device: %v\n", err)
  21. }
  22. fmt.Printf("Select default input device: %s\n", default_device.Name)
  23. param := portaudio.StreamParameters{}
  24. param.Input.Device = default_device
  25. param.Input.Channels = 1
  26. param.Input.Latency = default_device.DefaultLowInputLatency
  27. param.SampleRate = 16000
  28. param.FramesPerBuffer = 0
  29. param.Flags = portaudio.ClipOff
  30. config := sherpa.RecognizerConfig{}
  31. config.Feat = sherpa.FeatureConfig{SampleRate: 16000, FeatureDim: 80}
  32. flag.StringVar(&config.Model.EncoderParam, "encoder-param", "", "Path to the encoder.ncnn.param")
  33. flag.StringVar(&config.Model.EncoderBin, "encoder-bin", "", "Path to the encoder.ncnn.bin")
  34. flag.StringVar(&config.Model.DecoderParam, "decoder-param", "", "Path to the decoder.ncnn.param")
  35. flag.StringVar(&config.Model.DecoderBin, "decoder-bin", "", "Path to the decoder.ncnn.bin")
  36. flag.StringVar(&config.Model.JoinerParam, "joiner-param", "", "Path to the joiner.ncnn.param")
  37. flag.StringVar(&config.Model.JoinerBin, "joiner-bin", "", "Path to the joiner.ncnn.bin")
  38. flag.StringVar(&config.Model.Tokens, "tokens", "", "Path to the tokens file")
  39. flag.IntVar(&config.Model.NumThreads, "num-threads", 1, "Number of threads for computing")
  40. flag.StringVar(&config.Decoder.DecodingMethod, "decoding-method", "greedy_search", "Decoding method. Possible values: greedy_search, modified_beam_search")
  41. flag.IntVar(&config.Decoder.NumActivePaths, "num-active-paths", 4, "Used only when --decoding-method is modified_beam_search")
  42. flag.IntVar(&config.EnableEndpoint, "enable-endpoint", 1, "Whether to enable endpoint")
  43. flag.Float32Var(&config.Rule1MinTrailingSilence, "rule1-min-trailing-silence", 2.4, "Threshold for rule1")
  44. flag.Float32Var(&config.Rule2MinTrailingSilence, "rule2-min-trailing-silence", 1.2, "Threshold for rule2")
  45. flag.Float32Var(&config.Rule3MinUtteranceLength, "rule3-min-utterance-length", 20, "Threshold for rule3")
  46. flag.Parse()
  47. checkConfig(&config)
  48. log.Println("Initializing recognizer")
  49. recognizer := sherpa.NewRecognizer(&config)
  50. log.Println("Recognizer created!")
  51. defer sherpa.DeleteRecognizer(recognizer)
  52. stream := sherpa.NewStream(recognizer)
  53. defer sherpa.DeleteStream(stream)
  54. // you can choose another value for 0.1 if you want
  55. samplesPerCall := int32(param.SampleRate * 0.1) // 0.1 second
  56. samples := make([]float32, samplesPerCall)
  57. s, err := portaudio.OpenStream(param, samples)
  58. if err != nil {
  59. log.Fatalf("Failed to open the stream")
  60. }
  61. defer s.Close()
  62. chk(s.Start())
  63. var last_text string
  64. segment_idx := 0
  65. fmt.Println("Started! Please speak")
  66. for {
  67. chk(s.Read())
  68. stream.AcceptWaveform(int(param.SampleRate), samples)
  69. for recognizer.IsReady(stream) {
  70. recognizer.Decode(stream)
  71. }
  72. text := recognizer.GetResult(stream).Text
  73. if len(text) != 0 && last_text != text {
  74. last_text = strings.ToLower(text)
  75. fmt.Printf("\r%d: %s", segment_idx, last_text)
  76. }
  77. if recognizer.IsEndpoint(stream) {
  78. if len(text) != 0 {
  79. segment_idx++
  80. fmt.Println()
  81. }
  82. recognizer.Reset(stream)
  83. }
  84. }
  85. chk(s.Stop())
  86. }
  87. func chk(err error) {
  88. if err != nil {
  89. panic(err)
  90. }
  91. }
  92. func checkConfig(config *sherpa.RecognizerConfig) {
  93. // --encoder-param
  94. if config.Model.EncoderParam == "" {
  95. log.Fatal("Please provide --encoder-param")
  96. }
  97. if _, err := os.Stat(config.Model.EncoderParam); errors.Is(err, os.ErrNotExist) {
  98. log.Fatalf("--encoder-param %v does not exist", config.Model.EncoderParam)
  99. }
  100. // --encoder-bin
  101. if config.Model.EncoderBin == "" {
  102. log.Fatal("Please provide --encoder-bin")
  103. }
  104. if _, err := os.Stat(config.Model.EncoderBin); errors.Is(err, os.ErrNotExist) {
  105. log.Fatalf("--encoder-bin %v does not exist", config.Model.EncoderBin)
  106. }
  107. // --decoder-param
  108. if config.Model.DecoderParam == "" {
  109. log.Fatal("Please provide --decoder-param")
  110. }
  111. if _, err := os.Stat(config.Model.DecoderParam); errors.Is(err, os.ErrNotExist) {
  112. log.Fatalf("--decoder-param %v does not exist", config.Model.DecoderParam)
  113. }
  114. // --decoder-bin
  115. if config.Model.DecoderBin == "" {
  116. log.Fatal("Please provide --decoder-bin")
  117. }
  118. if _, err := os.Stat(config.Model.DecoderBin); errors.Is(err, os.ErrNotExist) {
  119. log.Fatalf("--decoder-bin %v does not exist", config.Model.DecoderBin)
  120. }
  121. // --joiner-param
  122. if config.Model.JoinerParam == "" {
  123. log.Fatal("Please provide --joiner-param")
  124. }
  125. if _, err := os.Stat(config.Model.JoinerParam); errors.Is(err, os.ErrNotExist) {
  126. log.Fatalf("--joiner-param %v does not exist", config.Model.JoinerParam)
  127. }
  128. // --joiner-bin
  129. if config.Model.JoinerBin == "" {
  130. log.Fatal("Please provide --joiner-bin")
  131. }
  132. if _, err := os.Stat(config.Model.JoinerBin); errors.Is(err, os.ErrNotExist) {
  133. log.Fatalf("--joiner-bin %v does not exist", config.Model.JoinerBin)
  134. }
  135. // --tokens
  136. if config.Model.Tokens == "" {
  137. log.Fatal("Please provide --tokens")
  138. }
  139. if _, err := os.Stat(config.Model.Tokens); errors.Is(err, os.ErrNotExist) {
  140. log.Fatalf("--tokens %v does not exist", config.Model.Tokens)
  141. }
  142. }