whisper.cpp icon indicating copy to clipboard operation
whisper.cpp copied to clipboard

Segment fault issue!?

Open HieuDevs opened this issue 1 year ago • 3 comments

I have implemented TTS for my application, everything is fine when sending one request at a time, but when running multiple requests simultaneously, I encounter a signal: segmentation fault error, and here is my code.

model, err := whisper.New(flags.GetModel())
if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	http.HandleFunc("/whisper", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPost {
			file, handler, err := r.FormFile("file")
			if err != nil {
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}
			defer file.Close()
			result := make(chan map[string]interface{})
			go func() {

				defer model.Close()
				data, err := controller.Process(model, file, handler.Filename, false, flags)
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
				result <- data
			}()
			//Send result to client
			w.WriteHeader(http.StatusOK)
			w.Header().Set("Content-Type", "application/json")
			if err := json.NewEncoder(w).Encode(<-result); err != nil {
				http.Error(w, "Error encoding JSON", http.StatusInternalServerError)
			}
		} else {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		}
	})
func Process(
	model whisper.Model,
	file multipart.File,
	fileName string,
	isTokenlizer bool,
	flags *Flags,
) (map[string]interface{}, error) {
	var data []float32
	context, err := model.NewContext()
	if err != nil {
		return nil, err
	}
	if err := flags.SetParams(context); err != nil {
		return nil, err
	}
	if strings.HasSuffix(fileName, ".wav") {
		dec := wav.NewDecoder(file)
		if buf, err := dec.FullPCMBuffer(); err != nil {
			return nil, err
		} else {
			fmt.Println("Resampling")
			data = resampler.SimpleResample(buf, whisper.SampleRate)
		}
	} else {
		return nil, errors.New("unsupported file format")
	}
	if err := context.Process(data, nil, nil); err != nil {
		return nil, errors.New("failed to process data")
	}
	segments := []map[string]interface{}{}
	if isTokenlizer {
		for {
			segment, err := context.NextSegment()
			if err != nil {
				break
			}
			tokens := []map[string]interface{}{}
			for _, token := range segment.Tokens {
				tokens = append(tokens, map[string]interface{}{
					"start": token.Start / 1000,
					"end":   token.End / 1000,
					"text":  token.Text,
				})
			}
			segments = append(segments, map[string]interface{}{
				"start":  segment.Start / 1000,
				"end":    segment.End / 1000,
				"text":   segment.Text,
				"tokens": tokens,
			})
		}
	} else {
		for {
			segment, err := context.NextSegment()
			if err != nil {
				break
			}
			segments = append(segments, map[string]interface{}{
				"start": segment.Start / 1000,
				"end":   segment.End / 1000,
				"text":  segment.Text,
			})
		}
	}

	return map[string]interface{}{
		"segments": segments,
	}, nil
}

HieuDevs avatar May 14 '24 06:05 HieuDevs

What does this have to do with whisper.cpp?

magnacartatron avatar May 14 '24 06:05 magnacartatron

What does this have to do with whisper.cpp?

so if i want place this code in function receive request then it's work but very slow

model, err := whisper.New(flags.GetModel())
if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

So can u explain for me

HieuDevs avatar May 14 '24 06:05 HieuDevs

From a quick glance, it looks like you're closing the model after the first request. You should be reusing the model (thread safe) but each context can only be used by a single request (at a time). Depending on the type / level of concurrency you are using, you may be better off using a worker pattern to do the transcription... as things will get very slow if you try to use more threads than your system has available.

bradmurray-dt avatar May 17 '24 17:05 bradmurray-dt