zoukankan      html  css  js  c++  java
  • 拼接音频

    现有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

  • 相关阅读:
    【H5】ie8如何兼容html5标签(hack)
    mysql数据库:分表、多表关联、外键约束、级联操作
    mysql数据库:mysql初识
    mysql数据库:数据类型、存储引擎、约束、
    并发编程:协程TCP、非阻塞IO、多路复用、
    并发编程:同步异步、队列、协程与实现方式
    并发编程: GIL锁、GIL与互斥锁区别、进程池与线程池的区别
    并发编程:生产消费模型、死锁与Rlock、线程、守护线程、信号量、锁
    并发编程:守护进程、互斥锁、案例、进程间通讯
    并发编程:进程、多道、进程执行顺序与常用属性
  • 原文地址:https://www.cnblogs.com/chenjunbiao/p/2045783.html
Copyright © 2011-2022 走看看