现有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);
}
}
}
}
{
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]);
}
}
}
}
}
{
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