使用Nodejs BOT SDK开发音频播放技能示例代码
DuerOS-王超 发布于2018-11-20 23:24 浏览:2720 回复:14
1
收藏

音频播放技能依次播放列表中的视频,并支持“暂停”,“继续”,“上一个”,“下一个”等常用音频指令。

意图配置:

示例代码:

const Bot = require('bot-sdk');
const privateKey = require("./rsaKeys.js").privateKey;
const musics = [
    {
        token: 'a0b923820dcc509a',
        url: 'xxx',
        singer: '歌手名',
        name: '歌曲名'
    },
    {
        token: '9d4c2f636f067f89',
        url: 'xxx',
        singer: '歌手名',
        name: '歌曲名'
    },
    {
        token: '4b5ce2fe28308fd9',
        url: 'xxx',
        singer: '歌手名',
        name: '歌曲名'
    },
    {
        token: 'a2f3e71d9181a67b',
        url: 'xxx',
        singer: '歌手名',
        name: '歌曲名'
    }
];

const default_image = 'https://skillstore.cdn.bcebos.com/icon/100/c709eed1-c07a-be4a-b242-0b0d8b777041.jpg';

class InquiryBot extends Bot {
    constructor(postData) {
        super(postData);
        this.curIndex = 0;
        this.waitAnswer();
        this.addLaunchHandler(() => {
            this.waitAnswer();
            this.setExpectSpeech(false);
            return {
                directives: [this.getDirective(0)],
                outputSpeech: '欢迎使用音乐播放器!',
            };
        });

        this.addIntentHandler('audio_play_intent', () => {
            this.waitAnswer();
            this.setExpectSpeech(false);
            return {
                directives: [this.getDirective(0), this.getTemplate2(musics[curIndex])],
                outputSpeech: '正在为你播放'
            };
        });
        //   system pause intent
        this.addIntentHandler('ai.dueros.common.pause_intent', () => {
            let directive = new Bot.Directive.AudioPlayer.Stop();
            this.waitAnswer();
            this.setExpectSpeech(false);
            return {
                directives: [directive, this.getTemplate2(musics[this.curIndex])],
                outputSpeech: '已经暂停播放'
            };
        });
        //   system continue intent
        this.addIntentHandler('ai.dueros.common.continue_intent', () => {
            let token = this.getSessionAttribute('token');
            let offsetInMilliSeconds = this.getSessionAttribute('offsetInMilliSeconds');
            this.updateCurrentSingIndex(token);
            this.waitAnswer();
            this.setExpectSpeech(false);
            return {
                directives: [this.getDirective(offsetInMilliSeconds), this.getTemplate2(musics[this.curIndex])],
                outputSpeech: `继续播放${musics[this.curIndex].name}`
            };
        });

        //  system next intent
        this.addIntentHandler('ai.dueros.common.next_intent', () => {
            let token = this.getSessionAttribute('token');
            this.updateNextSingIndex(token);
            this.waitAnswer();
            this.setExpectSpeech(false);
            return {
                directives: [this.getDirective(0), this.getTemplate2(musics[this.curIndex])],
                outputSpeech: `播放下一首:${musics[this.curIndex].name}...`
            };
        });

        //   system previous intent
        this.addIntentHandler('ai.dueros.common.previous_intent', () => {
            this.waitAnswer();
            this.setExpectSpeech(false);
            let token = this.getSessionAttribute('token');
            this.updatePreviousSingIndex(token);
            return {
                directives: [this.getDirective(0), this.getTemplate2(musics[this.curIndex])],
                outputSpeech: `播放上一首:${musics[this.curIndex].name}...`
            };
        });

        //   AudioPlayer.PlaybackStarted
        this.addEventListener('AudioPlayer.PlaybackStarted', event => {
            this.waitAnswer();
            this.setExpectSpeech(false);
            this.setSessionAttr(event);
        });

        //   client event PlaybackStopped
        this.addEventListener('AudioPlayer.PlaybackStopped', event => {
            this.waitAnswer();
            this.setExpectSpeech(false);
            this.setSessionAttr(event);
        });

        this.addEventListener('AudioPlayer.PlaybackFinished', event => {
            this.waitAnswer();
            this.setExpectSpeech(false);
            let token = this.getSessionAttribute('token');
            this.updateNextSingIndex(token);
            this.waitAnswer();
            this.setExpectSpeech(false);
            return {
                directives: [this.getDirective(0), this.getTemplate2(musics[this.curIndex])],
                outputSpeech: `播放下一首:${musics[this.curIndex].name}...`
            };
        });

        this.addDefaultEventListener(function () {
            this.waitAnswer();
            this.setExpectSpeech(false);

        });

        this.addIntentHandler('ai.dueros.common.default_intent', () => {
            this.waitAnswer();
            return {
                outputSpeech: '请对我说开始来播放音频。您也可以跟我说退出来退出技能。'
            };
        });

        this.addSessionEndedHandler(() => {
            let directive = new Bot.Directive.AudioPlayer.Stop();
            return {
                directives: [directive, this.getTemplate2('退出音乐播放,欢迎下次再来!')],
                outputSpeech: '退出音乐播放,欢迎下次再来!'
            };
        });
    }

    /**
     *  更新下一曲的index
     *
     *  @param {string} token 歌曲的id
     */
    updateNextSingIndex(token) {
        let self = this;
        musics.map((music, i) => {
            if (music.token === token) {
                self.curIndex = parseInt(i, 10) + 1 <= musics.length - 1 ? parseInt(i, 10) + 1 : musics.length - 1;
            }
            return null;
        });
    }

    /**
     *  更新上一首的index
     *
     *  @param {string} token 歌曲的id
     */
    updatePreviousSingIndex(token) {
        let self = this;
        musics.map((music, i) => {
            if (music.token === token) {
                self.curIndex = parseInt(i, 10) - 1 >= 0 ? parseInt(i, 10) - 1 : 0;
            }
            return null;
        });
    }

    /**
     *  更新当前正在播放歌曲的index
     *
     *  @param {string} token 歌曲的id
     */
    updateCurrentSingIndex(token) {
        let self = this;
        musics.map(function (music, i) {
            if (music.token === token) {
                self.curIndex = parseInt(i, 10);
            }
            return null;
        });
    }

    /**
     *  获取歌曲播放指令
     *
     *  @param {number} offset 歌曲播放的进度
     *  @return {Bot.Directive.AudioPlayer.Play} Play指令
     */
    getDirective(offset = 0) {
        let directive = new Bot.Directive.AudioPlayer.Play(musics[this.curIndex].url);
        directive.setToken(musics[this.curIndex].token);
        this.setSessionAttribute('token', musics[this.curIndex].token);
        directive.setOffsetInMilliSeconds(offset);
        return directive;
    }

    /**
     *  获取上图下文模版
     *
     *  @param {Object} music 歌曲详情
     *  @return {RenderTemplate} 渲染模版
     */
    getTemplate2(music) {
        let bodyTemplate = new Bot.Directive.Display.Template.BodyTemplate2();
        bodyTemplate.setToken(music.token);
        bodyTemplate.setBackGroundImage(default_image);
        bodyTemplate.setTitle(music.singer);
        bodyTemplate.setPlainContent(music.name);
        let renderTemplate = new Bot.Directive.Display.RenderTemplate(bodyTemplate);
        return renderTemplate;
    }

    /**
     *  获取文本展现模板
     *
     *  @param {string} text 歌曲详情
     *  @return {RenderTemplate} 渲染模版
     */
    getTemplate1(text) {
        let bodyTemplate = new Bot.Directive.Display.Template.BodyTemplate1();
        bodyTemplate.setPlainTextContent(text);
        let renderTemplate = new Bot.Directive.Display.RenderTemplate(bodyTemplate);
        return renderTemplate;
    }

    /**
     *  设置会话属性
     *
     *  @param {Object} event 客户端上报的事件,包含歌曲token和对应播放进度等信息
     */
    setSessionAttr(event) {
        this.setSessionAttribute('token', event.token);
        this.setSessionAttribute('offsetInMilliSeconds', event.offsetInMilliSeconds);
    }
}

exports.handler = function (event, context, callback) {
    try {
        let b = new InquiryBot(event);
        // 0: debug  1: online
        b.botMonitor.setEnvironmentInfo(privateKey, 0);
        b.run().then(function (result) {
            callback(null, result);
        }).catch(callback);
    } catch (e) {
        callback(e);
    }
}
收藏
点赞
1
个赞
共14条回复 最后由发个好time回复于2019-03-07 16:47
#3蓝兰兰111回复于2018-11-29

为什么已经引入的,但是还是报错说找不到。

0
#4DuerOS-王超回复于2018-11-30
#3 蓝兰兰111回复
为什么已经引入的,但是还是报错说找不到。[图片]

问题还存在么?

0
#5蓝兰兰111回复于2018-11-30
#4 DuerOS-王超回复
问题还存在么?

在百度云上部署了一下,问题解决了,还有一个问题就是我在真机上测试,为什么一直播放音乐的同时还一直是唤醒的状态?

0
#6DuerOS-王超回复于2018-11-30
#5 蓝兰兰111回复
在百度云上部署了一下,问题解决了,还有一个问题就是我在真机上测试,为什么一直播放音乐的同时还一直是唤醒的状态?
展开

是什么设备?技能id告知一下?

要不加一下开发qq群151767001,在里面跟我们联系? 

0
#712345vip5回复于2018-12-01

非常感谢,这个示例。作为小白 亲测后,实现了播放功能,但有几个点没有明白

 

token: 'a0b923820dcc509a',
        url: 'xxx',
        singer: '歌手名',
        name: '歌曲名'

这个token 作用是啥, 后面这串数字怎么产生的。 

 

ai.dueros.common.pause_intent 这类意图, 我在意图中设置后, 好像不起到作用。 

 

如果可能是否能做一段操作视频,让小白们完全理解这个操作呢。 谢谢

 

0
#8DuerOS-王超回复于2018-12-03
#7 12345vip5回复
非常感谢,这个示例。作为小白 亲测后,实现了播放功能,但有几个点没有明白 [代码] 这个token 作用是啥, 后面这串数字怎么产生的。 ai.dueros.common.pause_intent 这类意图, 我在意图中设置后, 好像不起到作用。 如果可能是否能做一段操作视频,让小白们完全理解这个操作呢。 谢谢
展开

Token是用来标识当前资源的。

视频资源请查阅 https://dueros.baidu.com/didp/news/technicalclass 中的协议开发部分。

0
#9z619479回复于2018-12-07
#8 DuerOS-王超回复
Token是用来标识当前资源的。 视频资源请查阅 https://dueros.baidu.com/didp/news/technicalclass 中的协议开发部分。
展开

请问这个Token是用来标识当前资源的token怎么生成的呢?

0
#10蓝兰兰111回复于2018-12-08
#6 DuerOS-王超回复
是什么设备?技能id告知一下? 要不加一下开发qq群151767001,在里面跟我们联系?
展开

想问一下,小度在家有没有本地缓存的机制?

0
#11DuerOS-王超回复于2018-12-11
#9 z619479回复
请问这个Token是用来标识当前资源的token怎么生成的呢?

token开发者自己定义就好了

0
#12wangwei8638回复于2018-12-14

为什么使用这段代码,下一个、上一个命令,只更新展现模板,音乐不更新,继续播放?

后在配置服务中调试都是正常的,可能模拟器有bug,建议更新哟,谢谢!

0
#13DuerOS-王超回复于2018-12-19
#12 wangwei8638回复
为什么使用这段代码,下一个、上一个命令,只更新展现模板,音乐不更新,继续播放? 后在配置服务中调试都是正常的,可能模拟器有bug,建议更新哟,谢谢!
展开

嗯,模拟器是有些问题,正在更新中

0
#14Andyan8851回复于2018-12-22

请教楼主一个问题:暂停后,使用“”继续播放“”口令,歌曲又从头开始。是什么地方的问题,检查了一下,停止的时候,端上传事件为:

"version": "v2.0",
  "session": {
    "new": false,
    "sessionId": "05d4a372-9cd3-4d8a-8548-5a862bc10131",
    "attributes": {
      "token": "a1b923820dcc509a",
      "offsetInMilliSeconds": 0
    }
  },

offsetInMilliSeconds 一直为0,所以继续播放返回的也为0,就从头播放了。谢谢解答!

0
#15发个好time回复于2019-03-07

同问继续播放重新开始播放

0
TOP