IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 关于M3U8视频播放的处理(Asp.Net MVC+video.js) -> 正文阅读

[开发测试]关于M3U8视频播放的处理(Asp.Net MVC+video.js)

先说说什么是M3U8

M3U8 是 Unicode 版本的 M3U,用 UTF-8 编码。"M3U" 和 "M3U8" 文件都是苹果公司使用的 HTTP Live Streaming(HLS) 协议格式的基础,这种协议格式可以在 iPhone 和 Macbook 等设备播放。

HLS 的工作原理是把整个流分成一个个小的基于 HTTP 的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的 extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。
HLS 只请求基本的 HTTP 报文,与实时传输协议(RTP)不同,HLS 可以穿过任何允许 HTTP 数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。

详细的就不多说了 上原文链接
作者:Whyn
链接:传送门
来源:简书
?

本次 前端用到的就是 大家都熟知的 Video.js??

后端 采用Asp.Net MVC 框架

视频转码工具?FFmpeg

关于FFmpeg 大家自行百度 这里部在详细介绍

好了 说了这么废话 上才艺

前端 我们需要定义一个容器 div? 通过video.js 动态生成播放器

在生成前,我们需要定义video的配置项,sources 代表播放文件 src为文件路径 type为文件类型

?上传文件就掠过了

    <div>
        <input type="text" id="filename" />
        <input type="file" name="File" id="FileS" />
        <button type="submit" id="updatefile">上传</button>

    </div>

    <div>video.js播放器</div>
    <video id="video" class="video-js" style="float:left">
    </video>

<script type="text/javascript">
  ///video.js 播放器配置项
    var options = {
        width: 800,
        height: 800,
        autoplay: true,
        controls: true,
        loop: false,
        preload: 'auto',
        sourceOrder: true,
        sources: [{
            src: "../../File/index.m3u8",
            type: 'application/x-mpegURL'
        }],
        bigPlayButton: true,
        textTrackDisplay: false,
        posterImage: false,
        errorDisplay: false,
        playbackRates: [0.5, 1, 1.5, 2, 3]
    }
    ///video.js 播放器初始化
    var videojsplayer = videojs('video', options);

$("#updatefile").click(function () {
        var files = $("#FileS").prop("files")[0];
        //声明FormData对象
        var formData = new FormData();
        //向FormData对象添加文件
        formData.append("file", files);
        formData.append("Name", $("#filename").val());
        $.ajax({
            type: "POST",
            url: "/Home/UploadingVideo/",
            async: true,///开启异步
            contentType: false,
            processData: false,          
            data: formData,
           
            success: function (data) {
                debugger

                if (data.src == "上传失败!") { alert(data.src); }
                else if (data.src == "没有找到该文件!") { alert(data.src); }
                else {
                    alert(data.Type);
                    window.location.reload();///用于刷新页面
                }
            },
            error: function (e) {
                console.log(e)
            }
        });
    })
</script>

后台我们接受传递过来的文件 进行保存和转码 HomeController代码

 public ActionResult UploadingVideo(HttpPostedFileBase file, string Name)
        {
            string src = "";
            string filePath = string.Empty;
            string guid = "";
            int type = -1;
            try
            {
                FFmpegHelper FF = new FFmpegHelper();
                //判断文件是否为空
                if (file != null)
                {
                    //获取文件类型
                    string fileExtension = System.IO.Path.GetExtension(file.FileName);
                    //自定义文件名(时间+唯一标识符+后缀)
                    guid = Guid.NewGuid().ToString();
                    string fileName = guid + fileExtension;
                    //判断是否存在需要的目录,不存在则创建 
                    if (!Directory.Exists(Server.MapPath("~/File/")))
                    { Directory.CreateDirectory(Server.MapPath("~/File/")); }

                    //若扩展名不为空则判断文件是否是指定视频类型
                    if (fileExtension != null)
                    {
                        VidoInfo mode = new VidoInfo();
                        mode.GUID = guid;
                        mode.Name = Name;
                        mode.Time = DateTime.Now;

                        if ("(.mp4)|(.avi)|(.flv)|(.rmvb)|(.wmv)|(.mov)".Contains(fileExtension))
                        {
                            mode.FileName = guid + ".m3u8";
                            //文件信息保存数据库
                            DB.VidoInfo.Add(mode);
                            DB.SaveChanges();

                            //判断是否存在需要的目录,不存在则创建 
                            if (!Directory.Exists(Server.MapPath("~/File/Video/")))
                            { Directory.CreateDirectory(Server.MapPath("~/File/Video/")); }

                            //拼接保存文件的详细路径
                            filePath = Server.MapPath("~/File/Video/") + fileName;

                            //保存文件
                            file.SaveAs(filePath);
                            //FF.VideoToTs(filePath, Server.MapPath("~/File/M3U8/") + guid+".ts");
                            //FF.TsToM3u8(filePath, Server.MapPath("~/File/M3U8/") + guid + ".m3u8", 25);
                            Thread thread2 = new Thread(new ThreadStart(delegate () { FF.TsToM3u8(filePath, Server.MapPath("~/File/M3U8/") + guid + ".m3u8", 25); }));
                            thread2.Start();

                            //拼接返回的Img标签
                            src = "/File/Video/" + fileName;
                            type = 1;
                        }
                        else if ("(.doc)|(.docx)".Contains(fileExtension))
                        {
                            mode.FileName = fileName;
                            //文件信息保存数据库
                            DB.VidoInfo.Add(mode);
                            DB.SaveChanges();

                            //判断是否存在需要的目录,不存在则创建 
                            if (!Directory.Exists(Server.MapPath("~/File/Office/")))
                            { Directory.CreateDirectory(Server.MapPath("~/File/Office/")); }

                            //拼接保存文件的详细路径
                            filePath = Server.MapPath("~/File/Office/") + fileName;
                            //保存文件
                            file.SaveAs(filePath);
                            //拼接返回的Img标签
                            src = "/File/Office/" + fileName;
                            type = 2;
                        }
                        else if ("(.xls)|(.xlsx)".Contains(fileExtension))
                        {
                            mode.FileName = fileName;
                            //文件信息保存数据库
                            DB.VidoInfo.Add(mode);
                            DB.SaveChanges();

                            //判断是否存在需要的目录,不存在则创建 
                            if (!Directory.Exists(Server.MapPath("~/File/Office/")))
                            { Directory.CreateDirectory(Server.MapPath("~/File/Office/")); }

                            //拼接保存文件的详细路径
                            filePath = Server.MapPath("~/File/Office/") + fileName;
                            //保存文件
                            file.SaveAs(filePath);
                            //拼接返回的Img标签
                            src = "/File/Office/" + fileName;
                            type = 3;
                        }
                        else if ("(.ppt)".Contains(fileExtension))
                        {
                            mode.FileName = fileName;
                            //文件信息保存数据库
                            DB.VidoInfo.Add(mode);
                            DB.SaveChanges();

                            //判断是否存在需要的目录,不存在则创建 
                            if (!Directory.Exists(Server.MapPath("~/File/Office/")))
                            { Directory.CreateDirectory(Server.MapPath("~/File/Office/")); }

                            //拼接保存文件的详细路径
                            filePath = Server.MapPath("~/File/Office/") + fileName;
                            //保存文件
                            file.SaveAs(filePath);
                            //拼接返回的Img标签
                            src = "/File/Office/" + fileName;
                            type = 4;
                        }
                        else if ("(.pdf)".Contains(fileExtension))
                        {
                            mode.FileName = fileName;
                            //文件信息保存数据库
                            DB.VidoInfo.Add(mode);
                            DB.SaveChanges();

                            //判断是否存在需要的目录,不存在则创建 
                            if (!Directory.Exists(Server.MapPath("~/File/Office/")))
                            { Directory.CreateDirectory(Server.MapPath("~/File/Office/")); }

                            //拼接保存文件的详细路径
                            filePath = Server.MapPath("~/File/Office/") + fileName;
                            //保存文件
                            file.SaveAs(filePath);
                            //拼接返回的Img标签
                            src = "/File/Office/" + fileName;
                            type = 5;
                        }
                    }
                    else
                    { src = "上传失败!"; }
                }
                else
                { src = "没有找到该文件!"; }
            }
            catch (Exception ex)
            {

                src = ex.Message;
            }
           
            return Json(new { src = src,Type = type }, JsonRequestBehavior.AllowGet);
        }

FFmpegHelper 压轴出场!

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;

namespace WebVideo
{
    public  class FFmpegHelper
    {
        //安装的ffmpeg的路径 写在配置文件的 你也可以直接写你的路径 D:\ffmpeg\bin\ffmpeg.exe
        //static string FFmpegPath = System.Configuration.ConfigurationManager.AppSettings["ffmepg"];



        /// <summary>
        /// 将ts文件转换为mu3u8文件
        /// </summary>
        /// <param name="tsUrl"></param>
        /// <param name="m3u8Url">这个路径不要带扩展名</param>
        /// <param name="videoLength">视频切片时长,默认5秒</param>
        public  void TsToM3u8(string tsUrl, string m3u8Url, int videoLength = 5)
        {
            //视频转码指令
            //string para = $@"ffmpeg -i {tsUrl} -c copy -map 0 -f segment -segment_list {m3u8Url}.m3u8 -segment_time 5 {m3u8Url}-%03d.ts";
            //这里是关键点,一般平时切视频都是用FFmpeg -i  地址 -c这样,但是在服务器时,这样调用可能找不到ffmpeg的路径 所以这里直接用ffmpeg.exe来执行命令
            //string para = $@"{FFmpegPath} -i {tsUrl} -c copy -map 0 -f segment -segment_list {m3u8Url}.m3u8 -segment_time 5 {m3u8Url}-%03d.ts";
            string para = string.Format("ffmpeg -i {0} -profile:v baseline -level 3.0 -start_number 0 -hls_time {1} -hls_list_size 0 -f hls {2}", tsUrl, videoLength, m3u8Url);
            RunMyProcess(para);
        }

        /// <summary>
        /// 执行cmd指令
        /// </summary>
        /// <param name="Parameters"></param>
        public static void RunMyProcess(string Parameters)
        {
            using (Process p = new Process())
            {
                try
                {
                    p.StartInfo.FileName = "cmd.exe";
                    p.StartInfo.UseShellExecute = false;//是否使用操作系统shell启动
                    p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                    p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                    p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                    p.StartInfo.CreateNoWindow = false;//不显示程序窗口                                                
                    p.Start();//启动程序
                    //向cmd窗口发送输入信息
                    p.StandardInput.WriteLine(Parameters + "&&exit");
                    p.StandardInput.AutoFlush = true;
                    p.StandardInput.Close();
                    //获取cmd窗口的输出信息
                    string output = p.StandardError.ReadToEnd(); //可以输出output查看具体报错原因

                    //等待程序执行完退出进程
                    p.WaitForExit();
                    p.Close();

                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }
}

?到这里就该跑跑跑试试了

效果图

?

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-08-25 12:30:46  更:2021-08-25 12:31:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 12:42:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码