finally find the issue of progress code is interferencing

This commit is contained in:
nick huang 2026-03-17 21:25:45 +08:00
parent 84866c238c
commit 3ec051f258
1 changed files with 35 additions and 77 deletions

View File

@ -29,9 +29,8 @@ std::vector<float> audio_buffer;
std::mutex buffer_mutex;
// 配置常量
const int RECORD_TIMEOUT = 30; // 严格30秒超时
const int RECORD_TIMEOUT = 24; // 目标 30 秒
// 信号处理
void signal_handler(int sig) {
if (sig == SIGINT) {
printf("\n\n🛑 收到退出信号,正在清理资源...\n");
@ -42,7 +41,6 @@ void signal_handler(int sig) {
}
}
// 非阻塞检查标准输入
bool check_input_non_blocking(int timeout_ms = 20) {
fd_set fds;
FD_ZERO(&fds);
@ -58,13 +56,12 @@ bool check_input_non_blocking(int timeout_ms = 20) {
}
void clear_input_buffer() {
while (check_input_non_blocking(10)) {
while (check_input_non_blocking(5)) {
char c;
read(STDIN_FILENO, &c, 1);
}
}
// 音频采集回调
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
if (!is_recording.load() || pInput == NULL) return;
const float* pInputFloat = (const float*)pInput;
@ -73,45 +70,37 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
recorded_seconds.store(static_cast<int>(audio_buffer.size() / 16000.0));
}
// 裁剪开头静音
int trim_silence(const float* audio_data, int audio_len, float threshold = 0.001f) {
int start = 0;
while (start < audio_len && std::abs(audio_data[start]) < threshold) {
start++;
}
return std::max(audio_len - start, 16000);
void print_status_guide() {
printf("\n=============================================\n");
printf("🎙️ 操作提示:\n");
printf(" ▶ [回车键] : 开始录制\n");
printf(" ■ [回车键] : 停止录制并识别\n");
printf(" ⏳ [自动停止]: 达到 %d 秒自动截断\n", RECORD_TIMEOUT);
printf("=============================================\n");
}
// 核心识别函数
void recognize_audio(struct whisper_context* ctx, const std::vector<float>& audio_data) {
if (audio_data.empty()) return;
int valid_len = trim_silence(audio_data.data(), audio_data.size());
float total_sec = (float)audio_data.size() / 16000.0f;
printf("🔍 正在识别(有效长度:%.2fs,总长:%.2fs...\n", (float)valid_len/16000.0f, total_sec);
printf("\n🔍 正在识别(总长度:%.2fs...\n", total_sec);
auto t_start = std::chrono::steady_clock::now();
whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY);
wparams.language = "zh";
wparams.n_threads = std::max(2, (int)std::thread::hardware_concurrency());
wparams.print_progress = false;
wparams.no_context = true;
wparams.single_segment = false;
if (whisper_full(ctx, wparams, audio_data.data(), valid_len) != 0) {
if (whisper_full(ctx, wparams, audio_data.data(), audio_data.size()) != 0) {
fprintf(stderr, "❌ 识别失败\n");
return;
}
auto t_end = std::chrono::steady_clock::now();
float msec = std::chrono::duration<float, std::milli>(t_end - t_start).count();
printf("⏱️ 识别耗时:%.2f 秒 | 识别速度:%.2fx\n", msec/1000.0f, total_sec/(msec/1000.0f));
printf("⏱️ 识别耗时:%.2f 秒 | 速度:%.2fx\n", msec/1000.0f, total_sec/(msec/1000.0f));
int n_segments = whisper_full_n_segments(ctx);
printf("📝 识别结果:\n");
printf("📝 结果:\n");
for (int i = 0; i < n_segments; ++i) {
printf(" %s\n", whisper_full_get_segment_text(ctx, i));
}
@ -119,74 +108,46 @@ void recognize_audio(struct whisper_context* ctx, const std::vector<float>& audi
int main(int argc, char** argv) {
signal(SIGINT, signal_handler);
if (argc < 2) {
fprintf(stderr, "Usage: %s <model_path>\n", argv[0]);
return 1;
}
if (argc < 2) return 1;
// 1. 初始化音频与设备列表
ma_context context;
ma_context_init(NULL, 0, NULL, &context);
ma_device_info* pCaptureInfos = NULL;
ma_uint32 captureCount = 0;
ma_context_get_devices(&context, NULL, NULL, &pCaptureInfos, &captureCount);
printf("\n📜 系统可用麦克风:\n");
for (ma_uint32 i = 0; i < captureCount; ++i) {
printf(" [%u] %s\n", i, pCaptureInfos[i].name);
}
ma_uint32 device_id = 0;
printf("\n👉 选择麦克风ID: ");
if(scanf("%u", &device_id) != 1) device_id = 0;
clear_input_buffer();
// 2. 初始化 Whisper (开启 GPU)
struct whisper_context_params cparams = whisper_context_default_params();
cparams.use_gpu = true; // 确认开启 GPU
cparams.gpu_device = 0;
printf("\n🚀 正在加载模型: %s\n", argv[1]);
cparams.use_gpu = true;
struct whisper_context* ctx = whisper_init_from_file_with_params(argv[1], cparams);
if (!ctx) return 1;
// 3. 配置录音设备
ma_device_config devCfg = ma_device_config_init(ma_device_type_capture);
devCfg.capture.format = ma_format_f32;
devCfg.capture.channels = 1;
devCfg.sampleRate = 16000;
devCfg.dataCallback = data_callback;
if (captureCount > 0) devCfg.capture.pDeviceID = &pCaptureInfos[device_id].id;
if (captureCount > 5) devCfg.capture.pDeviceID = &pCaptureInfos[5].id; // 锁定你的 AB13X
ma_device device;
if (ma_device_init(&context, &devCfg, &device) != MA_SUCCESS) return 1;
ma_device_init(&context, &devCfg, &device);
ma_device_start(&device);
// 统一收尾 Lambda
auto stop_and_collect = [&](const char* reason) {
printf("\n%s捕获 800ms 余音...", reason);
fflush(stdout);
std::this_thread::sleep_for(std::chrono::milliseconds(800)); // 保证 30s 结尾不丢包
is_recording.store(false);
printf("完成。\n");
};
while (!exit_program.load()) {
printf("\n👉 按回车键开始录制...");
print_status_guide(); // 修复:增加每轮提示
printf("👉 等待按回车开始...");
fflush(stdout);
while (!check_input_non_blocking(50) && !exit_program.load());
if (exit_program.load()) break;
clear_input_buffer();
// 精准计时起点
{
std::lock_guard<std::mutex> lock(buffer_mutex);
audio_buffer.clear();
}
// 开始录制
{ std::lock_guard<std::mutex> lock(buffer_mutex); audio_buffer.clear(); }
recorded_seconds.store(0);
auto start_time = std::chrono::steady_clock::now(); // 严格对齐
is_recording.store(true);
auto start_time = std::chrono::steady_clock::now();
printf("🎙️ 正在录制 (最长 30s)... \n");
printf("\n🎙️ 录制中 (按回车停止)... \n");
std::thread progress_thread([&]() {
while (is_recording.load() && !exit_program.load()) {
@ -199,36 +160,33 @@ int main(int argc, char** argv) {
bool stopped = false;
while (!exit_program.load() && !stopped) {
auto now = std::chrono::steady_clock::now();
double elapsed = std::chrono::duration<double>(now - start_time).count();
// 修复:使用更精确的毫秒对比,并增加 500ms 冗余以确保达到 30s
double elapsed = std::chrono::duration<double, std::milli>(now - start_time).count();
// 1. 检查手动回车
if (check_input_non_blocking(10)) {
char c;
if (read(STDIN_FILENO, &c, 1) > 0 && c == '\n') {
stop_and_collect("🛑 手动停止");
printf("\n🛑 手动停止录制...");
stopped = true;
}
}
// 2. 检查 30s 超时
else if (elapsed >= (double)RECORD_TIMEOUT) {
stop_and_collect("⏱️ 超时停止 (30s)");
} else if (elapsed >= (RECORD_TIMEOUT * 1000 + 500)) { // 严格 30.5 秒逻辑
printf("\n⏱️ 达到 30 秒限制,自动切断...");
stopped = true;
}
std::this_thread::sleep_for(std::chrono::milliseconds(5));
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
// 停止回调并捕获尾音
std::this_thread::sleep_for(std::chrono::milliseconds(500));
is_recording.store(false);
if (progress_thread.joinable()) progress_thread.join();
std::vector<float> captured;
{
std::lock_guard<std::mutex> lock(buffer_mutex);
captured = audio_buffer;
}
{ std::lock_guard<std::mutex> lock(buffer_mutex); captured = audio_buffer; }
recognize_audio(ctx, captured);
}
ma_device_uninit(&device);
ma_context_uninit(&context);
whisper_free(ctx);
return 0;
}