Merge #3351 into ln from refs/changes/3351/head 3358/target/1
author胡传军 <1224667075@qq.com>
Tue, 21 Apr 2026 05:05:40 +0000 (05:05 +0000)
committeraliyun3243248791 <accounts_67aaf52ad497cd558d73ac32@mail.teambition.com>
Tue, 21 Apr 2026 05:05:40 +0000 (05:05 +0000)
Code review from 胡传军

* refs/changes/3351/head: (7 commits squashed)

  - 关闭测试文件写入

  - 修复因没有按照帧结构发送数据导致服务端有坏数据问题

  - Merge branch &#39;ln&#39; of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into ln

  - 适配极速模式下的文字返回

  - 雷鸟音频卡顿优化

  - Merge branch &#39;ln&#39; of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into ln

  - 修改保底机制,防止首保过大

Signed-off-by: aliyun8003852482 <1224667075@qq.com>
Merged-by: 薛文强 <accounts_67aaf52ad497cd558d73ac32@mail.teambition.com>
link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/3351
code/sdk/zhihui/ai/media/ai_media_service_ext.cpp
code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c

index 1481f3f..e6550e4 100644 (file)
 extern "C" {
 #endif
 
+// #define USE_SILENCE_AUDIO_288
 // #define USE_SILENCE_AUDIO_288
 // 静音音频数据定义
 // 默认使用1100字节版本,定义 USE_SILENCE_AUDIO_288 可切换到288字节版本
 #ifdef USE_SILENCE_AUDIO_288
+#define USE_SILENCE_AUDIO
+
 // 288字节版本(纯MP3数据帧,无ID3标签)
 static const unsigned char silence_audio[288] = {
     0xff, 0xf3, 0x88, 0xc4, 0x00, 0x44, 0xc0, 0x03, 0x48, 0x00, 0x00, 0x00,
@@ -1898,7 +1901,7 @@ int32_t old_Start_AIVoice(AIVoiceDataCallback dataCallback, void* userData,
     
     task_cfg.create_queue_handle = CreateAIVoiceQueue;  // 设置队列创建函数
     task_cfg.attr.name = "AIVoiceThread";
-    task_cfg.attr.priority = (osPriority_t)28;  // 使用合适的优先级
+    task_cfg.attr.priority = (osPriority_t)(28+2);  // 使用合适的优先级
     task_cfg.attr.stack_size = 0x2000;  // 8KB栈空间
     task_cfg.func = AIVoiceThread;
     task_cfg.use_mem = USE_EXTEND_MEM;
@@ -2183,8 +2186,20 @@ int32_t AI_WriteAudioData(const uint8_t* data, uint32_t size)
     }
     MediaMutexUnLock(g_aiVoiceContextMutex);
 
+    // static uint32_t last_delay_us = 1;
+    int32_t ret=0;
+    #ifndef TIME_TICKS_TEST
+    ret = AudioStreamOutStreamWrite(data, size);
+    #else
     // 写入音频数据到输出流
-    int32_t ret = AudioStreamOutStreamWrite(data, size);
+    uint32_t current_tick = osKernelGetTickCount();
+    printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx AudioStreamOutStreamWrite current_tick: %u\n", current_tick);
+    ret = AudioStreamOutStreamWrite(data, size);
+    // printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx last_delay_us==1\r\n");
+    current_tick = osKernelGetTickCount();
+    printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx AudioStreamOutStreamWrite end current_tick: %u\n", current_tick);
+        // last_delay_us=0;
+    #endif
     
     if(g_aiVoiceContext->outputAudioFormat==MP3)
     {
@@ -2192,8 +2207,14 @@ int32_t AI_WriteAudioData(const uint8_t* data, uint32_t size)
         // 延迟时间(微秒)= (数据大小(字节)* 8 * 1000000) / 比特率(bps)
         // 当比特率更高时,延迟时间更短
         // 公式:延迟(微秒)= (size * 8 * 1000000) / bit_rate
-        uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*5)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
+        uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*7)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
+    #ifdef TIME_TICKS_TEST
+        printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx delay_ms %d\r\n",(uint32_t)((uint64_t)(size) * 8 * 1000000ULL / g_tts_audio_bit_rate)/1000);
+
         MEDIA_DEBUG_LOG("delay_us %d\r\n",delay_us);
+    #endif
+
+       
         
         // 确保延迟时间在合理范围内(最小10微秒)
         if (delay_us < 20) {
@@ -2202,7 +2223,7 @@ int32_t AI_WriteAudioData(const uint8_t* data, uint32_t size)
         usleep(delay_us-20);
         if (ret != 0) {
             retry_count++;
-            // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
+            MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
             usleep(delay_us*retry_count/10*5);
             goto AI_WRITE;
         }
index 93b82f3..6658fd7 100644 (file)
@@ -250,7 +250,7 @@ static uint32_t g_audio_timeout_ticks = 1500; // 音频超时tick数(默认1.5
 uint32_t g_last_binary_data_tick = 0;  // 最后一次接收二进制数据的tick
 
 // 音频数据最近缓存(环形缓冲区,仅保留最近数据)
-#define AUDIO_CACHE_BUFFER_SIZE  (1024*3)  // 8KB缓存
+#define AUDIO_CACHE_BUFFER_SIZE  (72*6*5)  // 8KB缓存
 static uint8_t g_audio_cache_buffer[AUDIO_CACHE_BUFFER_SIZE];
 static uint32_t g_audio_cache_pos = 0;  // 当前写入位置
 static uint32_t g_audio_cache_total = 0;  // 总写入数据量
@@ -291,7 +291,7 @@ static void ln_ws_reset_audio_cache(void);
 static uint32_t ln_ws_copy_from_ring_cache(uint32_t start_pos, uint32_t length, uint8_t* output);
 static int ln_ws_send_cached_audio_data(void);
 
-
+#define TIME_TICKS_TEST 0
 
 /* 握手成功回调:标记连接就绪 */
 static void ln_ws_on_open(int client)
@@ -347,7 +347,10 @@ static void ln_ws_message_callback(const char *raw_data, uint32_t timestamp)
         LN_WS_WARN("Invalid message\n");
     }
     LN_WS_DEBUG("on_message: %s\n", buf);
-
+#if TIME_TICKS_TEST
+    uint32_t current_tick = osKernelGetTickCount();
+    LN_WS_DEBUG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx on_message current_tick: %u\n", current_tick);
+#endif
     free(buf);
 }
 
@@ -613,6 +616,12 @@ static void ln_ws_audio_write_callback(uint32_t size)
 {
     LN_WS_DEBUG("Audio data written successfully: %u bytes\n", size);
 
+#if TIME_TICKS_TEST
+    uint32_t current_tick = osKernelGetTickCount();
+    LN_WS_DEBUG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx current_tick: %u\n", current_tick);
+#endif
+
+
     // 更新最后一次音频写入tick
     g_last_audio_write_tick = osKernelGetTickCount();
     g_audio_playback_active = true;
@@ -723,7 +732,14 @@ int ln_ws_send_audio_data(const uint8_t *audio_data, uint32_t audio_size, bool f
             LN_WS_ERROR("Failed to allocate memory for base64 encoding\n");
             return -1;
         }
-        
+        memset(audio_base64, 0, base64_size);
+        // LN_WS_DEBUG("audio_data before encode: \n");
+        // for(int i = 0; i < 32; i++)
+        // {
+        //     printf(" %02X",audio_data[i]);
+        // }
+        // LN_WS_DEBUG("audio_data end\n");
+
         size_t output_len = 0;
         int ret_encode = mbedtls_base64_encode((unsigned char*)audio_base64, base64_size - 1, &output_len, 
                                               audio_data, audio_size);
@@ -1153,7 +1169,11 @@ static void AIVoiceDataCallback_ln(const uint8_t* data, uint32_t size, void* use
 static void ai_binary_message_handler(const uint8_t *raw_data, uint32_t timestamp, uint32_t data_len)
 {
     LN_WS_INFO("Received binary message at %u, length: %d bytes\n", timestamp, data_len);
-    
+
+#if TIME_TICKS_TEST
+    uint32_t current_tick = osKernelGetTickCount();
+    LN_WS_DEBUG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ai_binary_message_handler current_tick: %u\n", current_tick);
+#endif
     // 收到二进制消息时,清除 ping 超时检测
     if (g_ping_timeout_active) {
         g_ping_timeout_active = false;
@@ -1168,15 +1188,20 @@ static void ai_binary_message_handler(const uint8_t *raw_data, uint32_t timestam
         LN_WS_WARN("Chat ID not matched\n");
         return;
     }
+    if(false==is_chat_id_matched() && g_audio_playback_active==false && g_audio_chat_ctx.finish_state == LN_CHAT_SENT_END_NO_REPLY)
+    {
+        LN_WS_DEBUG("Chat ID not matched, setting chat ID matched\n");
+        set_chat_id_matched();
+    }
 
     if (!raw_data || data_len == 0) {
         LN_WS_ERROR("Invalid binary data parameters\n");
         return;
     }
     
-    const size_t CHUNK_SIZE = 1024; // 1K 分块大小
+    const size_t CHUNK_SIZE = 1024*2; // 1K 分块大小
     
-    if (data_len <= CHUNK_SIZE) {
+    if (data_len <= CHUNK_SIZE || (g_audio_playback_active==false && data_len<=1024*5)) {
         // 数据小于等于1K,直接发送
         LN_WS_DEBUG("Sending data directly (size: %d bytes)\n", data_len);
         AI_SendAudioDataToQueue(raw_data, data_len);
@@ -1198,32 +1223,30 @@ static void ai_binary_message_handler(const uint8_t *raw_data, uint32_t timestam
             remaining -= current_chunk_size;
             
         }
+        LN_WS_DEBUG("All %d chunks sent successfully\n", chunk_count);
+    }
+
           // 更新最后一次音频写入tick
     
         // 如果音频播放从非活跃状态转为活跃状态,记录开始播放时间
-        if (!g_audio_playback_active) {
-            g_audio_playback_start_tick = osKernelGetTickCount();
-            LN_WS_INFO("Audio playback started at tick: %u\n", g_audio_playback_start_tick);
-            
-            // 触发音频播放开始事件
-            if (g_ws_message_callback != NULL) {
-                g_ws_message_callback(NULL, WS_CMD_AUDIO_PLAYBACK_START);
-            }
-            extern bool a2dp_is_connect;
-            if(a2dp_is_connect)
-            {
-                int ret = a2dp_src_start_playing(ln_bt_get_last_conned_device_Addr());  // 设置耳机的状态为播放
+    if (!g_audio_playback_active) {
+        g_audio_playback_start_tick = osKernelGetTickCount();
+        LN_WS_INFO("Audio playback started at tick: %u\n", g_audio_playback_start_tick);
+        
+        // 触发音频播放开始事件
+        if (g_ws_message_callback != NULL) {
+            g_ws_message_callback(NULL, WS_CMD_AUDIO_PLAYBACK_START);
+        }
+        extern bool a2dp_is_connect;
+        if(a2dp_is_connect)
+        {
+            int ret = a2dp_src_start_playing(ln_bt_get_last_conned_device_Addr());  // 设置耳机的状态为播放
+
+            LN_WS_DEBUG("a2dp_src_start_playing %d \n", ret);
 
-                LN_WS_DEBUG("a2dp_src_start_playing %d \n", ret);
-    
-            }
- 
         }
         g_audio_playback_active = true;
-
-    
         
-        LN_WS_DEBUG("All %d chunks sent successfully\n", chunk_count);
     }
 }
 
@@ -4093,7 +4116,7 @@ static int ln_ws_send_cached_audio_data(void)
     LN_WS_INFO("Sending cached audio data: %u bytes (wrapped=%d, start_pos=%u)\n", 
                total_size, g_audio_cache_wrapped, start_pos);
     
-    #define MAX_SEND_CHUNK_SIZE 512  // 每次最多发送4KB
+    #define MAX_SEND_CHUNK_SIZE 72*6  // 每次最多发送4KB
     
     int ret = 0;
     uint32_t remaining = total_size;