From ac1d4fd8ef875312d11acd4e4e5935ced542c227 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 06 Jul 2026 15:50:16 +0800
Subject: [PATCH] docs: record R222 merge closure

---
 C1.source/privatevoice.src/internal/engine/engine_windows.go |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/C1.source/privatevoice.src/internal/engine/engine_windows.go b/C1.source/privatevoice.src/internal/engine/engine_windows.go
index 17bfee2..6dd2ea2 100755
--- a/C1.source/privatevoice.src/internal/engine/engine_windows.go
+++ b/C1.source/privatevoice.src/internal/engine/engine_windows.go
@@ -4,7 +4,10 @@
 
 import (
 	"fmt"
+	"syscall"
 	"time"
+	"unsafe"
+
 	"voicesnap/internal/logger"
 	"voicesnap/internal/model"
 
@@ -18,7 +21,18 @@
 	hwInfo     string
 }
 
+var (
+	kernel32              = syscall.NewLazyDLL("kernel32.dll")
+	procGetShortPathNameW = kernel32.NewProc("GetShortPathNameW")
+)
+
 func newPlatformEngine(resolved model.ResolvedModel) (Engine, error) {
+	modelPath := windowsRuntimePath(resolved.Files["model"])
+	tokensPath := windowsRuntimePath(resolved.Files["tokens"])
+	if modelPath != resolved.Files["model"] || tokensPath != resolved.Files["tokens"] {
+		logger.Info("Using Windows short paths for sherpa runtime model files")
+	}
+
 	// Try DirectML first, then CPU fallback
 	providers := []struct {
 		name     string
@@ -32,10 +46,10 @@
 		config := sherpa.OfflineRecognizerConfig{}
 		config.FeatConfig.SampleRate = 16000
 		config.FeatConfig.FeatureDim = 80
-		config.ModelConfig.SenseVoice.Model = resolved.Files["model"]
+		config.ModelConfig.SenseVoice.Model = modelPath
 		config.ModelConfig.SenseVoice.Language = resolved.Profile.LanguageParam
 		config.ModelConfig.SenseVoice.UseInverseTextNormalization = 1
-		config.ModelConfig.Tokens = resolved.Files["tokens"]
+		config.ModelConfig.Tokens = tokensPath
 		config.ModelConfig.NumThreads = resolved.Profile.NumThreads
 		config.ModelConfig.Provider = p.provider
 		config.DecodingMethod = "greedy_search"
@@ -56,6 +70,48 @@
 	return nil, fmt.Errorf("failed to initialize sherpa-onnx with any provider")
 }
 
+func windowsRuntimePath(path string) string {
+	if path == "" {
+		return path
+	}
+	if isASCII(path) {
+		return path
+	}
+	short, ok := shortPathName(path)
+	if !ok || short == "" {
+		return path
+	}
+	return short
+}
+
+func isASCII(path string) bool {
+	for _, r := range path {
+		if r > 127 {
+			return false
+		}
+	}
+	return true
+}
+
+func shortPathName(path string) (string, bool) {
+	pathPtr, err := syscall.UTF16PtrFromString(path)
+	if err != nil {
+		return "", false
+	}
+
+	buf := make([]uint16, 32768)
+	ret, _, _ := procGetShortPathNameW.Call(
+		uintptr(unsafe.Pointer(pathPtr)),
+		uintptr(unsafe.Pointer(&buf[0])),
+		uintptr(len(buf)),
+	)
+	if ret == 0 || ret >= uintptr(len(buf)) {
+		return "", false
+	}
+
+	return syscall.UTF16ToString(buf[:int(ret)]), true
+}
+
 func (e *sherpaEngine) Recognize(samples []float32) (string, error) {
 	totalStart := time.Now()
 	streamStart := time.Now()

--
Gitblit v1.9.3