跳转至

Air8201G-通话中播放音频

作者:拓毅恒 | 最后修改:2026-07-22

一、通话中播放音频概述

  • 通话中播放外部音频:在 VoLTE 通话建立后,给对方播放音频文件或 TTS 文本的功能,可用于呼叫中心语音播报、通话中信息提示等场景。
  • 文件播放:支持播放 MP3、AMR 等格式的音频文件,框架自动从文件头解析采样率、位宽、声道数等参数。
  • TTS 播放:支持将文本转为语音播放,当前 V2046 固件 TTS 仅支持 16K 通话质量播放。
  • 通话模式:支持两种模式——呼入自动接听后播放(IS_DIAL=false)和主动拨出后播放(IS_DIAL=true)。

二、演示功能概述

本章节将演示如何使用 Air8201G 实现在 VoLTE 通话中给对方播放外部音频:

  1. 呼入自动接听播放:来电响铃 2 声后自动接听,音频通道建立后播放预设音频
  2. 主动拨出播放:设备自动拨打预设号码,对方接通后播放预设音频
  3. 文件播放模式:根据通话质量(8K/16K)自动选择对应采样率的 MP3 文件播放
  4. TTS 播放模式:将文本转为语音在通话中播放给对方

三、准备硬件环境

1、Air8201G 开发板一块;

2、TYPE-C USB 数据线一根;

3、Air8201配套的BTB扩展板一个;

Air8201G板子通过FPC线与BTB扩展板连接;

TYPE-C USB 数据线直接插到BTB扩展板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;

4、喇叭一个;

四、准备软件环境

4.1 工具 + 内核固件 + 脚本

在开始实践本示例之前,先筹备一下软件环境:

1.烧录工具: Luatools 工具

2.内核固件:Air8201G固件(基于Air780EGH)

3.LuatOS 需要的脚本和资源文件

脚本和资源文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8201/demo/codec

4.2 API 介绍

这里仅介绍本篇文档所使用的 API,详情请查看:API - cc

cc.extern_source(source, is_add_record, is_error_stop, codec_id, sample_rate, data_bits, channel_nums, is_signed)

通话中附加额外的音频数据播放,可在通话中向对方播放音频文件或 TTS 文本。

cc.quality()

获取当前通话质量(采样率),返回值:1=8K 低音质,2=16K 高音质。用于根据通话质量选择对应采样率的音频文件。

cc.on(event, callback)

注册通话事件回调函数。

cc.lastNum()

获取来电号码。

cc.accept(id)

接听来电。

cc.dial(id, number)

拨打电话。

五、代码演示

5.1 通话播放外部音频应用

--[[
@module  play_audio_during_cc
@summary 通话中播放音频(文件/TTS)
@version 1.0
@date    2026.07.08
@author  拓毅恒
@usage
本模块演示在VoLTE通话中给对方播放音频文件或TTS文本。
通话接通后在AUDIO_START事件中自动触发播放。

工作流程:
- 系统启动后初始化音频设备和CC
- 由宏IS_DIAL决定是主动拨号还是等待来电接听
- 通话建立(AUDIO_START)后,播放预设音频

注意事项:
1. 本demo使用新音频框架,固件需要V2048及以上的13/113号固件才能播放
2. 使用本demo时需要确认audio_drv.lua中初始化配置的音频框架audio_mode = "new" 才能播放
3. 传入音频文件时(如{"/luadb/test_16k.mp3"}),框架自动从文件头解析
   采样率、位宽、声道数等参数,并与当前通话参数自动校验
4. 校验不匹配会静默失败
5. 准备音频文件时需注意:确保文件是16bit、单声道的MP3文件
6. 支持16K/8K自适应播放,往对端播放只需要准备1个16K单通道的文件即可,TTS也支持在8K通话质量下播放

常用cc.extern_source调用示例:
1. 播放文件:   cc.extern_source({"/luadb/test_16k.mp3"})       -- 框架自动识别
2. 播放TTS:   cc.extern_source("你好,测试一下")                
3. 停止播放:  cc.extern_source(nil)
]]

-- 引入音频设备模块
local exaudio = require "exaudio"
local audio_drv = require "audio_drv"

-- ====================== 配置区域 ======================

-- 通话模式选择(二选一):
-- true = 主动拨出,false = 等待来电自动接听
local IS_DIAL = false
-- 主动拨出时的目标号码(IS_DIAL=true时有效)
local DIAL_NUMBER = "10000"

-- 音频播放
local PLAY_SOURCE = {"/luadb/test_16k.mp3"}     -- 播放文件模式,注意单个文件也要用table
-- local PLAY_SOURCE = "你好,测试一下,123456789"  -- 播放TTS模式

-- ====================== 全局状态变量 ======================
local call_counter = 0                 -- 响铃计数器
local caller_number = ""               -- 来电号码
local is_connected = false             -- 通话连接状态

-- ====================== 通话事件处理 ======================
-- 来电自动接听模式
local function handle_incoming_call(status)
    if status == "INCOMINGCALL" then
        -- 获取来电号码
        caller_number = cc.lastNum() or "未知号码"
        call_counter = call_counter + 1
        log.info("play_audio_during_cc", "收到来电,号码:", caller_number, "响铃次数:", call_counter)
        -- 响铃2声后自动接听
        if call_counter >= 2 then
            log.info("play_audio_during_cc", "自动接听来电")
            cc.accept(0)
            call_counter = 0
        end
    end
end

-- 主动拨号模式
local function handle_outgoing_call(status)
    if status == "MAKE_CALL_OK" then
        log.info("play_audio_during_cc", "拨号请求成功")
    elseif status == "CONNECTED" then
        log.info("play_audio_during_cc", "电话已接通")
    elseif status == "MAKE_CALL_FAILED" then
        log.info("play_audio_during_cc", "拨号失败")
    end
end

-- 通话中播放外部音频(接通音频通道后触发)
local function play_extern_source()
    local quality = cc.quality()
    log.info("play_audio_during_cc", "通话质量:", quality, "(1=8K低音质, 2=16K高音质)")

    -- 先清理上一次通话可能残留的extern_source状态,确保第二次也能播放
    cc.extern_source()
    -- 播放音频
    local ok = cc.extern_source(PLAY_SOURCE)
    if ok then
        if type(PLAY_SOURCE) == "table" then
            log.info("extern_demo", "开始播放文件:", PLAY_SOURCE[1])
        elseif type(PLAY_SOURCE) == "string" then
            log.info("extern_demo", "开始播放TTS:", PLAY_SOURCE)
        end
    else
        log.error("play_audio_during_cc", "播放失败,可能音频参数与通话不匹配")
    end
end

-- 主动拨号模式的定时拨号处理
local function handle_dial_timer()
    log.info("play_audio_during_cc", "开始拨号:", DIAL_NUMBER)
    cc.dial(0, DIAL_NUMBER)
end

-- CC_IND事件处理器
local function handle_cc_ind(status)
    log.info("CC状态", status)

    -- 根据模式分发事件
    if IS_DIAL then
        handle_outgoing_call(status)
    else
        handle_incoming_call(status)
    end

    -- AUDIO_START:音频通道已建立,可以播放外部音频
    if status == "AUDIO_START" then
        play_extern_source()
    end

    -- SPEECH_START:通话开始
    if status == "SPEECH_START" then
        is_connected = true
        log.info("play_audio_during_cc", "通话已建立")
    end

    -- 需要处理的通用状态
    if status == "READY" then
        sys.publish("CC_READY")  -- 发布系统就绪事件
        -- 主动拨号模式:电话系统就绪后自动拨号
        if IS_DIAL then
            sys.timerStart(handle_dial_timer, 1000)
        end
    elseif status == "HANGUP_CALL_DONE" or status == "MAKE_CALL_FAILED" or status == "DISCONNECTED" then
        -- 通话结束,关闭PA保留driver下次通话时快速恢复
        exaudio.pm(audio.SHUTDOWN)
        is_connected = false
        call_counter = 0
        log.info("play_audio_during_cc", "通话结束")
    end
end

-- ====================== 主事件处理器 ======================
sys.subscribe("CC_IND", handle_cc_ind)

-- ====================== 电话系统初始化 ======================
local function init_cc()
    -- 初始化音频设备
    audio_drv.initAudioDevice()

    -- 等待电话系统就绪
    sys.waitUntil("CC_READY")

    -- 初始化电话功能
    cc.init(audio_drv.getMultimediaId())

    log.info("play_audio_during_cc", IS_DIAL and "主动拨号模式" or "来电接听模式")
    log.info("cc_extern_source_demo", "播放模式: ", type(PLAY_SOURCE) == "table" and "FILE" or "TTS")
    log.info("play_audio_during_cc", "电话系统初始化完成")
end

-- 启动初始化任务
sys.taskInit(init_cc)

log.info("play_audio_during_cc", "通话外部音频播放模块加载完成")

六、功能演示

6.1 选择功能

首先注释掉 main.lua 中默认通话功能模块,打开通话中播放外部音频功能模块:

6.2 配置播放参数

audio_drv.lua 文件中,将音频框架改为 new

6.3 烧录代码

使用 Luatools 将代码烧录到 Air8201G 开发板或核心板中。

6.4 电话系统初始化完成

烧录完毕后,系统会自动初始化音频设备和电话系统。日志中会显示模块加载和初始化完成信息。

6.5 来电响铃(呼入模式)

当有来电时,日志会显示来电号码和响铃次数。响铃 2 声后自动接听。

6.5.1 启动拨号(主动拨出模式)

如果在开头设置为 IS_DIAL = true,设备将自动拨打预设号码,日志显示拨号请求。

6.7 通话建立并播放音频

对方接通后,显示 SPEECH_STARTAUDIO_START 状态,自动触发播放外部音频。

6.8 播放完成

音频播放完成后,显示 EXT_SRC_DONE 事件。通话继续,等待对方挂断。

6.9 通话结束

对方挂断后,通话结束,显示 DISCONNECTED 状态,系统自动关闭 PA 节省功耗。

七、总结

至此,我们演示了使用 Air8201G 在 VoLTE 通话中播放外部音频的全过程:

  1. 呼入自动播放:来电响铃 2 声后自动接听,音频通道建立后自动播放预设音频
  2. 主动拨出播放:设备自动拨打预设号码,对方接通后播放预设音频
  3. 文件播放模式:根据通话质量自动选择对应采样率的音频文件,支持 MP3/AMR 格式
  4. TTS 播放模式:将文本转为语音在通话中播放给对方

注意事项

  • 本 demo 使用新音频框架,需确认 audio_drv.luaaudio_mode = "new"
  • 固件需要 V2046 及以上的 13/113 号固件才能播放
  • 音频文件准备好 8K 和 16K 两种采样率,运行时通过 cc.quality() 判断后选择
  • 当前 V2046 固件 TTS 仅支持 16K 通话质量播放,8K 时会静默失败
AI问答