
YoC播放器中支援的碼流url類型有如下幾種:
流類型 URL字首 URL格式
http流 http(s):// http(s)://ip:port/xx.mp3
檔案流 file:// file:///fatfs0/xx.mp3?avformat=%s&avcodec=%u&channel=%u&rate=%u
記憶體流 mem:// mem://addr=%u&size=%u&avformat=%u&avcodec=%u&channel=%u&rate=%u
fifo流 fifo:// fifo://tts/1?avformat=%s&avcodec=%u&channel=%u&rate=%u
由于fifo是基于生産者-消費者原理來實作的,我們可以基于fifo碼流類型來實作實時語音合成碼流播放。使用者在建立fifo後,通過将fifo傳遞給播放器播放。與此同時可不斷從網絡上讀取tts流,寫入fifo中。
示例代碼如下:
//核心代碼片段
static player_t* g_player;
static nsfifo_t* g_tts_fifo;
static void _ptask(void *arg)
{
int fd;
int cnt = 0, rc, wlen;
char *val, *pos;
uint8_t reof = 0;
web_session_t *session;
/* 建立一個http會話 */
session = web_session_create();
/* 向指定位址發起http請求 */
rc = web_session_get(session, "http://www.srcbin.net/ai/result.mp3", 3);
if (rc) {
LOGE(TAG, "web_session_get fail. rc = %d, code = %d, phrase = %s", rc, session->code, session->phrase);
goto err;
}
/* 擷取内容的長度 */
val = (char*)dict_get_val(&session->hdrs, "Content-Length");
CHECK_RET_TAG_WITH_GOTO(val != NULL, err);
fd = session->fd;
LOGD(TAG, "content len = %d", atoi(val));
for (;;) {
/* 擷取fifo的可寫指針及長度 */
wlen = nsfifo_get_wpos(g_tts_fifo, &pos, 8*1000);
/* 擷取播放器fifo讀端是否退出(可能播放出錯) */
nsfifo_get_eof(g_tts_fifo, &reof, NULL);
if (wlen <= 0 || reof) {
LOGE(TAG, "get wpos err. wlen = %d, reof = %d", wlen, reof);
break;
}
/* 從網絡套接字中讀取資料 */
rc = sock_readn(fd, pos, wlen, 6*1000);
if (rc <= 0) {
LOGE(TAG, "readn err. rc = %d", rc);
break;
}
/* 設定寫指針 */
nsfifo_set_wpos(g_tts_fifo, rc);
cnt += rc;
}
LOGD(TAG, "rc = %8d, cnt = %8d", rc, cnt);
err:
/* 銷毀web會話資源 */
web_session_destroy(session);
return;
}
/ 建立fifo,指定fifo位址和大小 /
g_tts_fifo = nsfifo_open("fifo://tts/1", O_CREAT, 64*1024);
if (g_tts_fifo) {
/* 建立 _ptask任務,用于通過網絡擷取碼流資料 */
aos_task_new("xx_task", _ptask, NULL, 6*1024);
/* 設定播放器取流逾時時間 */
player_ioctl(g_player, PLAYER_CMD_RCVTIMEO, AOS_WAIT_FOREVER);
/* 播放之前建立的fifo碼流 */
player_play(g_player, "fifo://tts/1", 0);