Twilio로 재생을 일시 중지하고 다시 시작하는 방법에 대한 해결책은 아니지만 완벽합니다.
기본 아이디어는 재생 명령이 생성 된 시간과 Gather
URL이 호출 된 시간의 차이를 계산하는 것입니다. 차이점 (잠시 동안 완전한 세계를 가정 함)은 발신자가 중단되기 전에 콘텐츠가 재생 된 거리 여야합니다. 그런 다음 호출자가 다시 시작할 준비가되면 Play
명령을 생성하여 앱 서버가 전체 콘텐츠가 아닌 부분적으로 오프셋 된 콘텐츠를 재생하도록하고 재생이 다시 시작되어야하는 지점에서 바로 시작되도록해야합니다. 오디오 파일 내용의 일부만을 제공해야 함). 기본적으로 일시 중지/다시 시작 기능을 에뮬레이트합니다.
저는 이것을 구현했으며 더 많이 또는 덜 효과적입니다. 불완전한 세계는 네트워크 대기 시간, 처리 지연 (Twilio가 Play
명령을 받고 재생 자원을 검색하고 실제로 재생되기 시작하는 시간), 그리고 버튼을 치는 것 사이의 지연과 실제로 Gather
호출을 수신하는 것 사이의 지연이 모두 영향을 미친다. 정확성. 그러나 요구 사항이 지나치게 엄격하지 않은 경우 대부분의 경우 정확성이 충분할 것입니다.
여기는 C#에서했던 개념 증명입니다 (몇 달이 지났습니다. 아직 게시 된 것처럼 작동하기를 바랍니다). 또한 빨리 감기와 되감기를 포함한 실험이 포함됩니다.이 실험은 단순히 이력서가 실제로 시작되는 곳을 조정하는 것입니다 (그리고 Pause
명령을 건너 뜁니다). 아래
코드 Play
, Pause
으로 TwiML PausablePlayController.cs를 생성하고, 다른 명령을위한 것이다.
Play
동작 (TwiML 명령 아님)은 콘텐츠 재생을위한 TwiML을 생성합니다. 재생은 Pause
동작을 가리키는 Gather
으로 싸여 있기 때문에 인터럽트 가능합니다. Gather
의 URL에는 재생이 시작된 시간 스탬프가 포함되어 있습니다 (이전에 이미 오프셋 된 경우 다시 계산합니다).
Pause
동작 (TwiML 명령 아님)은 일시 중지 또는 검색을 수행하는 TwiML을 생성합니다. 4 회 되감기 아래의 코드에서 처음부터 5 회 다시 시작, 6 회 빨리 감기 및 다른 모든 키는 일시 중지를 수행합니다.
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;
}
}
트릭의 나머지 부분은 (내가 더 이상 불행하게도, 기준이없는 어떤 다른 포스트에있는 코드의 부분) 부분 오디오 콘텐츠를 스트림이 다음 컨트롤러입니다.단순히 오프셋의 주어진 밀리 초 동안 오디오 콘텐츠가 시작되는 곳을 계산하고 그 지점에서 나머지 콘텐츠를 스트리밍하는 것입니다.
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;
}
}
대략적인 접근 방식입니다. 재생 중에 어느 시점에서 중단이 발생했는지 파악하는 것이 문제입니다. 나는 솔루션을 가지고 있다고 생각합니다. – LB2
@ LB2, 이것을위한 해결책을 찾았습니까? 입력을 받았을 때 파일 재생이 어디로 진행되었는지 알 수 있습니까? – jdmcnair
@ LB2 완벽하지는 않지만 네트워크 지연 분산 및 기타 "교차 바람"의 영향을 받기는하지만 위조의 방법을 찾았습니다 (다음 주에 접근 방식을 게시 할 예정입니다). 내 답을 게시하려면 개념 증명에 액세스 할 수 없으므로 조정하십시오. – LB2