Update record auto flow.
This commit is contained in:
parent
f04bdac2af
commit
2a7d3f0d9e
|
|
@ -216,6 +216,9 @@ esp_err_t _http_event_handler(esp_http_client_event_t* evt) {
|
|||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGE(TAG, "HTTP request error");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGW(TAG, "HTTP disconnected");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -317,7 +320,7 @@ void send_audio_transcription(const char* filepath) {
|
|||
.event_handler = _http_event_handler,
|
||||
.buffer_size = 4096,
|
||||
.buffer_size_tx = 4096,
|
||||
.timeout_ms = 60000, // Increased timeout to 60 seconds
|
||||
.timeout_ms = 120000, // Increased timeout to 120 seconds to handle network interruptions
|
||||
.skip_cert_common_name_check = false, // Don't skip cert name check
|
||||
.keep_alive_enable = true,
|
||||
.use_global_ca_store = true,
|
||||
|
|
@ -382,6 +385,8 @@ void send_audio_transcription(const char* filepath) {
|
|||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err));
|
||||
// Wait a bit to allow WiFi to reconnect if needed
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
|
||||
// 清理
|
||||
|
|
|
|||
|
|
@ -314,9 +314,8 @@ void app_main(void) {
|
|||
// vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
// }
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ESP_ERROR_CHECK(record_wav(rx_chan));
|
||||
}
|
||||
// Record for 2 cycles as before
|
||||
ESP_ERROR_CHECK(record_wav(rx_chan, 2));
|
||||
|
||||
esp_pm_config_esp32_t pm_config = {
|
||||
.max_freq_mhz = 240, .min_freq_mhz = 240, .light_sleep_enable = false};
|
||||
|
|
|
|||
246
main/record.c
246
main/record.c
|
|
@ -44,24 +44,20 @@ esp_err_t wait_for_time_sync(int timeout_seconds) {
|
|||
int retry = 0;
|
||||
const int max_retry = timeout_seconds;
|
||||
|
||||
// Wait for the SNTP sync status to be complete
|
||||
while (esp_sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET &&
|
||||
retry < max_retry) {
|
||||
ESP_LOGI(TAG, "等待NTP时间同步... (%d/%d)", retry + 1, max_retry);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
retry++;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
// 检查时间是否有效(2000年之后)
|
||||
if (timeinfo.tm_year > 100) {
|
||||
ESP_LOGW(TAG, "时间未同步,正在等待NTP...");
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (retry >= max_retry) {
|
||||
ESP_LOGE(TAG, "NTP同步超时");
|
||||
// Get the current time after sync attempt
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
if (timeinfo.tm_year < 100) {
|
||||
ESP_LOGE(TAG, "NTP同步失败或超时,时间无效");
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
|
|
@ -69,51 +65,211 @@ esp_err_t wait_for_time_sync(int timeout_seconds) {
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
char* get_file_name_from_time(void) {
|
||||
wait_for_time_sync(10);
|
||||
char* get_file_name_from_time_now(void) {
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(record_file_name, 48, "/sdcard/Record_%Y%m%d%H%M%S.wav", &timeinfo);
|
||||
return record_file_name;
|
||||
}
|
||||
|
||||
esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan) {
|
||||
esp_err_t ret = ESP_OK;
|
||||
// Queue to communicate between recording task and ASR task
|
||||
static QueueHandle_t asr_queue = NULL;
|
||||
|
||||
uint32_t byte_rate = I2S_SAMPLE_RATE * I2S_CHAN_NUM * I2S_SAMPLE_BITS / 8;
|
||||
uint32_t wav_size = byte_rate * RECORD_TIME_SEC;
|
||||
// Counter for total recordings expected and completed
|
||||
static volatile uint32_t total_recordings_expected = 0;
|
||||
static volatile uint32_t total_recordings_completed = 0;
|
||||
|
||||
const wav_header_t wav_header = WAV_HEADER_PCM_DEFAULT(
|
||||
wav_size, I2S_SAMPLE_BITS, I2S_SAMPLE_RATE, I2S_CHAN_NUM);
|
||||
// Structure to pass parameters to the recording task
|
||||
typedef struct {
|
||||
i2s_chan_handle_t i2s_rx_chan;
|
||||
int loop_count;
|
||||
} record_task_params_t;
|
||||
|
||||
get_file_name_from_time();
|
||||
ESP_LOGI(TAG, "Opening file %s", record_file_name);
|
||||
FILE* f = fopen(record_file_name, "w");
|
||||
ESP_LOGI(TAG, "fopen error: %s", strerror(errno));
|
||||
ESP_RETURN_ON_FALSE(f, ESP_FAIL, TAG, "error while opening wav file");
|
||||
// Task for recording audio and saving to file
|
||||
static void record_task(void* pvParameters) {
|
||||
record_task_params_t* params = (record_task_params_t*)pvParameters;
|
||||
i2s_chan_handle_t i2s_rx_chan = params->i2s_rx_chan;
|
||||
int loop_count = params->loop_count;
|
||||
|
||||
ESP_RETURN_ON_FALSE(fwrite(&wav_header, sizeof(wav_header_t), 1, f), ESP_FAIL,
|
||||
TAG, "error while writing wav header");
|
||||
// Free the parameters since they're no longer needed
|
||||
free(params);
|
||||
|
||||
/* Start recording */
|
||||
size_t wav_written = 0;
|
||||
static int16_t i2s_readraw_buff[DMA_BUF_LEN * sizeof(int16_t)];
|
||||
ESP_ERROR_CHECK(i2s_channel_enable(i2s_rx_chan));
|
||||
while (wav_written < wav_size) {
|
||||
if (wav_written % byte_rate < sizeof(i2s_readraw_buff)) {
|
||||
ESP_LOGI(TAG, "Recording: %" PRIu32 "/%ds", wav_written / byte_rate + 1,
|
||||
RECORD_TIME_SEC);
|
||||
|
||||
for (int i = 0; i < loop_count; i++) {
|
||||
ESP_LOGI(TAG, "Starting recording cycle %d/%d", i + 1, loop_count);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
uint32_t byte_rate = I2S_SAMPLE_RATE * I2S_CHAN_NUM * I2S_SAMPLE_BITS / 8;
|
||||
uint32_t wav_size = byte_rate * RECORD_TIME_SEC;
|
||||
|
||||
const wav_header_t wav_header = WAV_HEADER_PCM_DEFAULT(
|
||||
wav_size, I2S_SAMPLE_BITS, I2S_SAMPLE_RATE, I2S_CHAN_NUM);
|
||||
|
||||
get_file_name_from_time_now();
|
||||
ESP_LOGI(TAG, "Opening file %s", record_file_name);
|
||||
FILE* f = fopen(record_file_name, "w");
|
||||
ESP_LOGI(TAG, "fopen error: %s", strerror(errno));
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "error while opening wav file");
|
||||
continue; // Move to the next iteration
|
||||
}
|
||||
|
||||
if (fwrite(&wav_header, sizeof(wav_header_t), 1, f) != 1) {
|
||||
ESP_LOGE(TAG, "error while writing wav header");
|
||||
fclose(f);
|
||||
continue; // Move to the next iteration
|
||||
}
|
||||
|
||||
/* Start recording */
|
||||
size_t wav_written = 0;
|
||||
static int16_t i2s_readraw_buff[DMA_BUF_LEN * sizeof(int16_t)];
|
||||
while (wav_written < wav_size) {
|
||||
if (wav_written % byte_rate < sizeof(i2s_readraw_buff)) {
|
||||
ESP_LOGI(TAG, "Recording: %" PRIu32 "/%ds", wav_written / byte_rate + 1,
|
||||
RECORD_TIME_SEC);
|
||||
}
|
||||
size_t bytes_read = 0;
|
||||
ESP_ERROR_CHECK(i2s_channel_read(i2s_rx_chan, i2s_readraw_buff,
|
||||
sizeof(i2s_readraw_buff), &bytes_read,
|
||||
pdMS_TO_TICKS(100)));
|
||||
/* Write the samples to the WAV file */
|
||||
if (fwrite(i2s_readraw_buff, bytes_read, 1, f) != 1) {
|
||||
ESP_LOGE(TAG, "error while writing samples to wav file");
|
||||
fclose(f);
|
||||
continue; // Move to the next iteration
|
||||
}
|
||||
wav_written += bytes_read;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Recording done! Flushing file buffer");
|
||||
fclose(f);
|
||||
|
||||
// Send signal to ASR task with the recorded file name
|
||||
char* file_name_copy = malloc(strlen(record_file_name) + 1);
|
||||
if (file_name_copy != NULL) {
|
||||
strcpy(file_name_copy, record_file_name);
|
||||
|
||||
// Send the file name to the ASR queue
|
||||
if (xQueueSend(asr_queue, &file_name_copy, portMAX_DELAY) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Failed to send file name to ASR queue");
|
||||
free(file_name_copy);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for file name copy");
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Completed recording cycle %d/%d", i + 1, loop_count);
|
||||
|
||||
// Optional: Add a small delay between recordings to ensure file operations
|
||||
// complete
|
||||
if (i < loop_count - 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
size_t bytes_read = 0;
|
||||
ESP_ERROR_CHECK(i2s_channel_read(i2s_rx_chan, i2s_readraw_buff,
|
||||
sizeof(i2s_readraw_buff), &bytes_read,
|
||||
pdMS_TO_TICKS(100)));
|
||||
/* Write the samples to the WAV file */
|
||||
ESP_RETURN_ON_FALSE(fwrite(i2s_readraw_buff, bytes_read, 1, f), ESP_FAIL,
|
||||
TAG, "error while writing samples to wav file");
|
||||
wav_written += bytes_read;
|
||||
}
|
||||
i2s_channel_disable(i2s_rx_chan);
|
||||
ESP_LOGI(TAG, "Recording done! Flushing file buffer");
|
||||
fclose(f);
|
||||
send_audio_transcription(record_file_name);
|
||||
return ret;
|
||||
|
||||
// Delete this task as it's done
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// Task for performing ASR processing
|
||||
static void asr_task(void* pvParameters) {
|
||||
char* received_file_name = NULL;
|
||||
|
||||
while (1) {
|
||||
// Wait for a file name from the recording task
|
||||
if (xQueueReceive(asr_queue, &received_file_name, portMAX_DELAY) ==
|
||||
pdTRUE) {
|
||||
if (received_file_name != NULL) {
|
||||
// Check if this is a termination signal
|
||||
if (strcmp(received_file_name, "TERMINATE") == 0) {
|
||||
free(received_file_name);
|
||||
break; // Exit the loop to terminate the task
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Received file for ASR: %s", received_file_name);
|
||||
|
||||
// Perform ASR processing
|
||||
send_audio_transcription(received_file_name);
|
||||
|
||||
// Free the received file name
|
||||
free(received_file_name);
|
||||
received_file_name = NULL;
|
||||
|
||||
// Increment the completed counter
|
||||
total_recordings_completed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Task is terminating
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan, int loop_count) {
|
||||
// Reset counters
|
||||
total_recordings_expected = loop_count;
|
||||
total_recordings_completed = 0;
|
||||
|
||||
// Create the queue if it doesn't exist
|
||||
if (asr_queue == NULL) {
|
||||
asr_queue = xQueueCreate(
|
||||
loop_count + 2,
|
||||
sizeof(char*)); // Queue size adjusted for expected recordings
|
||||
if (asr_queue == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create ASR queue");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the ASR processing task if it doesn't exist
|
||||
static TaskHandle_t asr_task_handle = NULL;
|
||||
if (asr_task_handle == NULL) {
|
||||
BaseType_t task_ret = xTaskCreate(asr_task, "asr_task", 4096, NULL,
|
||||
tskIDLE_PRIORITY + 2, &asr_task_handle);
|
||||
if (task_ret != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Failed to create ASR task");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare parameters for the recording task
|
||||
record_task_params_t* params = malloc(sizeof(record_task_params_t));
|
||||
if (params == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for recording task parameters");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
params->i2s_rx_chan = i2s_rx_chan;
|
||||
params->loop_count = loop_count;
|
||||
|
||||
// Create the recording task with parameters
|
||||
TaskHandle_t record_task_handle = NULL;
|
||||
BaseType_t task_ret = xTaskCreate(record_task, "record_task", 4096, params,
|
||||
tskIDLE_PRIORITY + 3, &record_task_handle);
|
||||
if (task_ret != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Failed to create recording task");
|
||||
free(params);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Wait for the recording task to complete
|
||||
while (record_task_handle != NULL) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // Check every 100ms
|
||||
|
||||
// Check if the recording task still exists
|
||||
if (eTaskGetState(record_task_handle) == eDeleted) {
|
||||
record_task_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all ASR processing to complete
|
||||
while (total_recordings_completed < total_recordings_expected) {
|
||||
ESP_LOGI(TAG, "Waiting for ASR processing: %d/%d completed",
|
||||
total_recordings_completed, total_recordings_expected);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // Check every second
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "base.h"
|
||||
|
||||
esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan);
|
||||
esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan, int loop_count);
|
||||
|
||||
void get_time_init();
|
||||
esp_err_t print_current_time();
|
||||
|
|
|
|||
Loading…
Reference in New Issue