拼接音频

摘要:
现有的AMR语音音频n段需要在HTML5浏览器上播放,并且在输出流时进行拼接,不需要在浏览器中使用脚本分段播放。根据AMR文件格式的分析,在拼接时,需要删除从第2段开始的AMR字节流中的前六个字节。“#!以下两个示例指定Content-Length并使用分块输出,其中分块输出在移动设备浏览器中不可用。分块输出方法:publicclassAudioHandler:IHttpHandler{publicvoid ProcessRequest{//参数验证stringvoiceUrl=Path.GetFileNameWithoutExtension;if{context.Response.StatusCode=404;context.Respress.End();return;}//获取音频地址IAudioContractaudio=AudioManager。Create();GetAudioUrlsArgsargs=newGetAudioUrlsArgs(){VoiceUrl=VoiceUrl};varresult=audio.GetAudioUrls;如果(result==null&&result.Status!=ExecuteStatus.OK&&result.Data==null&&result.Data.AddressList==null&&结果.Data.AAddressList.Count˂=0){context.Respons.StatusCode=404;context.Respress.End();return;}//输出配置上下文。回答ContentType=“audio/amr”;context.Response.BufferOutput=false;//输出音频。移动设置不支持chunkedList<string>filePaths=result。数据地址列表;intcount=文件路径计数;对于{OutputChunkedAudio(context,filePaths[i],(i==0)?

现有AMR的语音音频n段,要求在HTML5浏览器上播放,并且是在输出流时即进行拼接,不需在浏览器用脚本进行分段播放。根据 AMR文件格式分析 可知,拼接时需要将从第2段开始的amr字节流中去掉前6个字节"#!AMR "。以下两个例子分别是指定Content-Length和使用chunked方式输出,其中chunked方式在移动设备浏览器中不可用。

chunked输出方式:

public class AudioHandler : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
//参数验证
string voiceUrl = Path.GetFileNameWithoutExtension(context.Request.Url.LocalPath);
if (string.IsNullOrEmpty(voiceUrl))
{
context.Response.StatusCode
= 404;
context.Response.End();
return;
}

//获取音频地址
IAudioContract audio = AudioManager.Create();
GetAudioUrlsArgs args
= new GetAudioUrlsArgs(){ VoiceUrl = voiceUrl};
var result
= audio.GetAudioUrls(args);
if (result == null && result.Status != ExecuteStatus.OK && result.Data == null &&
result.Data.AddressList
== null && result.Data.AddressList.Count <= 0)
{
context.Response.StatusCode
= 404;
context.Response.End();
return;
}

//输出配置
context.Response.ContentType = "audio/amr";
context.Response.BufferOutput
= false;

//输出音频, 移动设置不支持chunked
List<string> filePaths = result.Data.AddressList;
int count = filePaths.Count;
for (int i = 0; i < count; i++)
{
OutputChunkedAudio(context, filePaths[i], (i
== 0) ? true : false);
}
context.Response.Flush();

}

public bool IsReusable
{
get { return false; }
}

private void OutputChunkedAudio(HttpContext context, string filePath, bool first)
{
bool deleted = first ? true : false;

Stream outputStream
= context.Response.OutputStream;
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[6];
while (true)
{
int count = fileStream.Read(buffer, 0, 6);
if (count == 0)
{
return;
}
if (!deleted)
{
deleted
= true;
continue;
}

//context.Response.Write(Encoding.UTF8.GetString(buffer));
outputStream.Write(buffer, 0, count);
}

}
}

}

指定Content-Length的方式:

public class AudioHandler : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
//参数验证
string voiceUrl = Path.GetFileNameWithoutExtension(context.Request.Url.LocalPath);
if (string.IsNullOrEmpty(voiceUrl))
{
context.Response.StatusCode
= 404;
context.Response.End();
return;
}

//获取音频地址
IAudioContract audio = AudioManager.Create();
GetAudioUrlsArgs args
= new GetAudioUrlsArgs(){ VoiceUrl = voiceUrl};
var result
= audio.GetAudioUrls(args);
if (result == null && result.Status != ExecuteStatus.OK && result.Data == null &&
result.Data.AddressList
== null && result.Data.AddressList.Count <= 0)
{
context.Response.StatusCode
= 404;
context.Response.End();
return;
}

//输出配置
context.Response.ContentType = "audio/amr";
context.Response.BufferOutput
= false;

//输出音频
List<byte> data = new List<byte>();
List
<string> filePaths = result.Data.AddressList;
int count = filePaths.Count;
for (int i = 0; i < count; i++)
{
LoadFullAudio(filePaths[i], (i
== 0) ? true : false, ref data);
}
context.Response.AppendHeader(
"Content-Length", data.Count.ToString());
context.Response.OutputStream.Write(data.ToArray(),
0, data.Count);
context.Response.Flush();

}

public bool IsReusable
{
get { return false; }
}

private void LoadFullAudio(string filePath, bool first, ref List<byte> data)
{
bool deleted = first ? true : false;

using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[6];
while (true)
{
int count = fileStream.Read(buffer, 0, 6);
if (count == 0)
{
return;
}
if (!deleted)
{
deleted
= true;
continue;
}

for (int i = 0; i < count; i++)
{
data.Add(buffer[i]);
}

}

}
}

}

f

免责声明:文章转载自《拼接音频》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇NSFastEnumeration在Orchard模块中访问模块本地的AppSettings下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

拦截器、过滤器、监听器的区别和使用

拦截器与过滤器的区别 :1. 拦截器是基于java的反射机制的。而过滤器是基于函数回调,Spring框架支持,可Spring中的数据源、事务管理等。2.使用范围不同:拦截器不依赖与servlet容器,过滤器依赖与servlet容器。3. 拦截器只能对action请求起作用,针对类,拦截器可以多次被调用。 而过滤器则可以对几乎所有的请求起作用,在容器启动是初...

一个Mini的ASP.NET Core框架的实现

转自:https://www.cnblogs.com/edisonchou/p/aspnet_core_mini_implemention_introduction.html 一、ASP.NET Core Mini 在2019年1月的微软技术(苏州)俱乐部成立大会上,蒋金楠老师(大内老A)分享了一个名为“ASP.NET Core框架揭秘”的课程,他用不到2...

flutter -------- 页面跳转和传值

在安卓原生开发中,页面跳转可以用Intent类来具体实现: Intent intent =new Intent(MainActivity.this,second.class); startActivity(intent); 页面的传值也有很多种 Flutter的传值方式是路由传值; 例如,我们想传一些关于我们点击的ListView条目的信息...

Ajax Array Json 示例

functionfunctionName(){ var list=newArray(); $("td.classA").each(function(){ list.push($(this).attr('id')); }); if(li...

微信小程序开发系列(一)小程序开发初体验

开发小程序所需的基本技能 关于小程序的介绍和使用场景这里不作介绍,这个系列的文章会一步一步地带领大家快速地学习和掌握小程序的开发。 关于还没有接触过小程序的开发者来说,最关心的问题无非就是,开发小程序,我需要掌握哪些技能? 从我学习小程序的经验中得出,开发小程序的基本要求: 如果你是一名已经工作1年以上的前端工程师,你几乎不用学习任何新的东西就可以快速上...

几个javascript函数

1.功能说明:根据控件类型和名字(根据title值)查找控件 使用举例:getField('select', 'Segment Code').value = ""; function getField(fieldType,fieldTitle) {var docTags = document.getElementsByTagName(fieldType);...