Twilio 播放暂停/恢复 [英] Twilio play pause/resume

查看:38
本文介绍了Twilio 播放暂停/恢复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Twilio 是否支持暂停和恢复播放内容.换句话说,我有相当长的文件可以播放给调用者,我正在尝试找到一种实现暂停和播放的方法.恢复功能.在播放某些内容的过程中,我希望用户能够按一个数字暂停,然后再按一个数字从暂停的音频文件中的同一点恢复播放.

Does Twilio have any support for pausing and resuming playback of content. In other words, I have fairly long files that will be played to the caller, and I'm trying to find a way to implement pause & resume functionality. In the middle of a play of some content, I want to have user ability to press a digit to pause, and then later press a digit again to resume play from the same point in audio file where it was paused.

Twilio 是否支持类似的功能?

Does Twilio support something like that?

推荐答案

我确实找到了一个可行的解决方案,尽管并不完美,但它可以解决如何使用 Twilio 暂停和恢复播放.

I did find a workable, albeit not perfect, solution to how to pause and resume a playback with Twilio.

基本思想是计算生成播放命令和Gather URL 被调用.区别(暂时假设完美世界)应该是内容在被调用者打断之前播放了多远.然后,当调用者准备好恢复时,生成 Play 命令,这样它会导致您的应用服务器不提供完整的内容,而是提供部分偏移的内容,这些内容在播放应该恢复的点开始(这可能意味着需要实施仅传送部分音频文件内容的机制).这实质上会模拟暂停/恢复功能.

The basic idea is to calculate the difference in time between when the play command was generated and the time when Gather URL is called. The difference (assuming perfect world for a moment) should be how far the content was played before being interrupted by the caller. Then, when caller is ready to resume, generate Play command such that it causes your app server to deliver not full content, but rather partial offset'ed content that begins right at a point where playback should resume (which likely implies that a mechanism to deliver only part of audio file content would need to be implemented). This would essentially emulate pause/resume functionality.

我已经实现了这个,它或多或少地起作用.网络延迟、处理延迟(Twilio 收到 Play 命令、检索播放资源和实际开始播放之间的时间)以及点击按钮和实际播放之间的延迟,不完美的世界开始发挥作用接收Gather 调用都会影响准确性.但如果您的要求不是太严格,那么对于大多数情况来说,准确度可能已经足够了.

I've implemented this and it more-or-less works. The imperfect world comes into play where network latency, delays in processing (time between Twilio receives the Play command, retrieves the play resource, and actually starts playing), as well as delay between hitting the button and actually receiving the Gather call all affect the accuracy. But if your requirements aren't too strict, the accuracy is probably decent enough for most cases.

这是我在 C# 中所做的概念验证(已经几个月了 - 希望它仍然像发布的那样有效).它还包括快进和快退的实验,这只是调整恢复实际开始的位置(并跳过 Pause 命令).

Here is the proof-of-concept that I did in C# (it's been a few months - hope it still works as posted). It also includes experimentation with fast-forwarding and rewinding, which is simply adjusting where resume actually starts (and skipping Pause command).

以下代码用于 PausablePlayController.cs,它使用 PlayPause 和其他命令生成 TwiML.

The code below is for PausablePlayController.cs which generates the TwiML with Play, Pause, and other commands.

Play 操作(不是 TwiML 命令)生成用于播放内容的 TwiML.播放是可中断的,因为它被包裹在 Gather 中,它指向 Pause 动作.Gather 的 URL 包含播放开始位置的时间戳(如果之前已经偏移,则及时计算).

Play action (not TwiML command) generates TwiML for playing content. The playback is interrupt-able as it is wrapped in Gather which points to Pause action. The URL of Gather contains a time-stamp of where playback began (and in case it was already offset previously, calculates it back in time).

Pause 操作(不是 TwiML 命令)生成 TwiML 以进行暂停或搜索.在下面的代码中,4 次倒带,5 次从头开始,6 次快进,任何其他键都会暂停.

Pause action (not TwiML command) generates TwiML for doing the pause or seeking. In code below 4 rewinds, 5 restarts from beginning, 6 fast-forwards, and any other key does the pause.

public class PausablePlayController : ApiController
{
    private const int seekDeltaMilliseconds = 5000;

    // GET api/pausableplay/5
    [HttpGet]
    public System.Xml.Linq.XElement Play(string audio, int millisecondsOffset)
    {
        TwilioResponse twiml = new TwilioResponse();
        twiml.BeginGather(new { action = this.Url.Link("PausablePlayPause", new { audio = audio, playStart = DateTime.UtcNow.Subtract(new TimeSpan(0, 0, 0, 0, millisecondsOffset)).Ticks/*.ToString("o", System.Globalization.CultureInfo.InvariantCulture )*/ }), method = "GET", numDigits = "1" });
        twiml.Play(this.Url.Link("OffsetPresentations", new { audio = audio, millisecondsOffset = millisecondsOffset }));
        twiml.EndGather();

        return twiml.Element;
    }

    [HttpGet]
    public System.Xml.Linq.XElement Pause(string audio, long playStart, int digits)
    {
        DateTime playStartDate = new DateTime(playStart, DateTimeKind.Utc);
        int millisecondsOffset = (int)DateTime.UtcNow.Subtract(playStartDate).TotalMilliseconds;
        TwilioResponse twiml = new TwilioResponse();
        switch(digits)
        {
            case 4:
                millisecondsOffset -= (millisecondsOffset < seekDeltaMilliseconds) ? millisecondsOffset : seekDeltaMilliseconds;
                return Play(audio, millisecondsOffset);
            case 5:
                return Play(audio, 0);
            case 6:
                millisecondsOffset += seekDeltaMilliseconds;
                return Play(audio, millisecondsOffset);
            default:
                {
                    twiml.BeginGather(new { action = this.Url.Link("PausablePlayPlay", new { audio = audio, millisecondsOffset = millisecondsOffset }), method = "GET", numDigits = "1" });
                    twiml.Pause(120);
                    twiml.EndGather();
                    twiml.Say("Goodbye!");
                }
                break;
        }
        return twiml.Element;
    }
}

剩下的技巧是在下一个控制器中,它可以流式传输部分音频内容(我在其他一些帖子中找到的部分代码,不幸的是,我不再参考).它所做的只是简单地计算给定毫秒偏移量的音频内容的开始位置,并从该点开始流式传输其余内容.

The rest of the trick is in this next controller that streams partial audio content (parts of code I found in some other post to which I no longer have reference, unfortunately). All it does is simply calculates where the audio content for a given milliseconds of offset begins and streams the rest of the content from that point.

public class OffsetedContentController : ApplicationController
{
    const int BufferSize = 32 * 1024;

    // GET api/prompts/5
    public Task<HttpResponseMessage> Get(string audio, [FromUri]int millisecondsOffset)
    {
        string contentFilePath = audio;  // Build physical path for your audio content

        if (!File.Exists(contentFilePath)) 
        { 
            return Task.FromResult(Request.CreateResponse(HttpStatusCode.NotFound)); 
        }            
        // Open file and read response from it. If read fails then return 503 Service Not Available                       
        try            
        {                
            // Create StreamContent from FileStream. FileStream will get closed when StreamContent is closed                
            FileStream fStream = new FileStream(contentFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, useAsync: true);
            fStream.Position = getPositionOffset(millisecondsOffset);
            HttpResponseMessage response = Request.CreateResponse();
            response.Content = new StreamContent(fStream);
            response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("audio/ulaw");
            return Task.FromResult(response);    
        }
        catch (Exception e)          
        {             
            return Task.FromResult(Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, e)); 
        }
    }

    private long getPositionOffset(int millisecondsOffset)
    {
        long bytePosition = millisecondsOffset * 4;
        return bytePosition;
    }
}

这篇关于Twilio 播放暂停/恢复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆