微服务[学成在线] day13:使用FFmpeg进行格式转换以及m3u8文件生成、文件分块上传接口实现

本文介绍了如何在微服务项目中使用FFmpeg进行视频格式转换,生成m3u8文件,以及实现文件分块上传接口。内容涉及在线学习需求分析、视频编码、播放器技术选型、搭建学习中心前端和媒资管理。通过FFmpeg进行视频编码,利用HLS协议实现边下载边播放。此外,还探讨了使用video.js作为H5播放器,并配置Nginx媒体服务器。最后,介绍了媒资管理系统的文件上传流程,包括断点续传和文件分块合并。
摘要由CSDN通过智能技术生成

😎 知识点概览

为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。

本章节为【学成在线】项目的 day13 的内容

  • FFmpeg 的基本使用
  • 使用 m3u8video.js技术实现视频的在线播放
  • 搭建媒资服务工程实现文件的分块储存

目录

内容会比较多,小伙伴们可以根据目录进行按需查阅。

一、在线学习需求分析

0x01 需求描述

学成在线作为在线教育网站,提供多种学习形式,包括:录播、直播、图文、社群等,学生登录进入学习中心即可

在线学习,本章节将开发录播课程的在线学习功能,需求如下:

1、学生可以在 windows 浏览器上在线观看视频。

2、播放器具有快进、快退、暂停等基本功能。

3、学生可以方便切换章节进行学习。

什么是录播课程?

录播课程就是提供录制好课程视频,供用户在线点播,反复学习。

课程视频如何管理?

媒资管理系统专门来管理课程视频,用户视频文件上传到媒资系统,并对视频进行编码处理。

0x02 视频点播解决方案

流媒体方案

详细参考:https://baike.baidu.com/item/%E6%B5%81%E5%AA%92%E4%BD%93/98740?fr=aladdin

概括理解:流媒体就是将视频文件分成许多小块儿,将这些小块儿作为数据包通过网络发送出去,实现一边传输视
频 数据 包一边观看视频。

  • 流式传输

    在网络上传输音、视频信息有两个方式:下载 和 流式传输。

    下载:就是把音、视频文件完全下载到本机后开始播放,它的特点是必须等到视频文件下载完成方可播放,播放等待时间较长,无法去播放还未下载的部分视频。

    流式传输:就是客户端通过链接视频服务器实时传输音、视频信息,实现 “边下载边播放”。

    流式传输包括如下两种方式:

    • 1) 顺序流式传输

      即顺序下载音、视频文件,可以实现边下载边播放,不过,用户只能观看已下载的视频内容,无法快进到未下载的视频部分,顺序流式传输可以使用 Http 服务器来实现,比如 NginxApache 等。

    • 2)实时流式传输

      实时流式传输可以解决顺序流式传输无法快进的问题,它与Http流式传输不同,它必须使用流媒体服务器并且使用流媒体协议来传输视频,它比 Http 流式传输复杂。常见的实时流式传输协议有RTSPRTMPRSVP 等。

  • 流媒体系统的概要结构

    通过流媒体系统的概要结构,学习流媒体系统的基本业务流程。

1、将原始的视频文件通过编码器转换为适合网络传输的流格式,编码后的视频直接输送给媒体服务器。
原始的视频文件通常是事先录制好的视频,比如通过摄像机、摄像头等录像、录音设备采集到的音视频文
件,体积较大,要想在网络上传输需要经过压缩处理,即通过编码器进行编码 。

2、媒体服务获取到编码好的视频文件,对外提供流媒体数据传输接口,接口协议包括 :HTTPRTSPRTMP 等 。

3、播放器通过流媒体协议与媒体服务器通信,获取视频数据,播放视频。

点播方案

本项目包括点播和直播两种方式,我们先调研一下几个点播的方案,如下:

  1. 播放器通过 http 协议从 http 服务器上下载视频文件进行播放

    问题:必须等到视频下载完才可以播放,不支持快进到某个时间点进行播放

  2. 播放器通过 rtmp 协议连接媒体服务器以实时流方式播放视频

    使用rtmp协议需要架设媒体服务器,造价高,对于直播多采用此方案。

  3. 播放器使用 HLS 协议连接 http 服务器(NginxApache等)实现近实时流方式播放视频

    HLS协议规定:基于 Http 协议,视频封装格式为 ts,视频的编码格式为 H264,音频编码格式为MP3AAC或者 AC-3

那么 HLS 是什么?

HLS 的工作方式是:将视频拆分成若干 ts 格式的小文件,通过 m3u8 格式的索引文件对这些 ts 小文件建立索引。一般 10 秒一个 ts 文件,播放器连接 m3u8 文件播放,当快进时通过 m3u8 即可找到对应的索引文件,并去下载对应的 ts 文件,从而实现快进、快退以近实时的方式播放视频。

IOS、Android 设备、及各大浏览器都支持 HLS 协议。

详细参考:https://baike.baidu.com/item/HLS/8328931?fr=aladdin

采用 HLS 方案即可实现边下载边播放,并可不用使用 rtmp 等流媒体协议,不用构建专用的媒体服务器,节省成本。所以本项目点播方案确定为方案 3

二、视频编码

0x01 视频编码格式

先来看一下百度百科中的简介

详情参考 :https://baike.baidu.com/item/%E8%A7%86%E9%A2%91%E7%BC%96%E7%A0%81/839038

首先我们要分清文件格式和编码格式:

文件格式:是指 .mp4.avi.rmvb 等 这些不同扩展名的视频文件的文件格式 ,视频文件的内容主要包括视频和音频,其文件格式是按照一 定的编码格式去编码,并且按照该文件所规定的封装格式将视频、音频、字幕等信息封装在一起,播放器会根据它们的封装格式去提取出编码,然后由播放器解码,最终播放音视频。

音视频编码格式:通过音视频的压缩技术,将视频格式转换成另一种视频格式,通过视频编码实现流媒体的传输。

比如:一个 .avi 的视频文件原来的编码是 a,通过编码后编码格式变为 b,音频原来为 c,通过编码后变为d

0x02 FFmpeg 的基本使用

我们将视频录制完成后,使用视频编码软件对视频进行编码,本项目 使用 FFmpeg 对视频进行编码。

FFmpeg 被许多开源项目采用,QQ影音、暴风影音、VLC 等。

下载:FFmpeg https://www.ffmpeg.org/download.html#build-windows

下载完成后,将 ffmpeg 解压到磁盘下,设置环境变量 FFMPEG_HOME 的值为 ffmpeg 的安装目录

%FFMPEG_HOME%/bin 添加到环境变量Path

0x03 生成 m3u8/ts 文件

使用 ffmpeg 生成 m3u8 的步骤如下:

第一步:先将 avi 视频转成 mp4

ffmpeg.exe -i lucene.avi -c:v libx264 -s 1280x720 -pix_fmt yuv420p -b:a 63k -b:v 753k -r 18 lucene.mp4

下面把各参数意思大概讲讲,大概了解意思即可,不再此展开流媒体专业知识的讲解。

  • -c:v 视频编码为 x264x264 编码是 H264 的一种开源编码格式。

  • -s 设置分辨率

  • -pix_fmt yuv420p:设置像素采样方式,主流的采样方式有三种,YUV4:4:4YUV4:2:2YUV4:2:0,它的作用是根据采样方式来从码流中还原每个像素点的YUV(亮度信息与色彩信息)值。

  • -b 设置码率,-b:a-b:v 分别表示音频的码率和视频的码率,-b 表示音频加视频的总码率。码率对一个视频质量有很大的作用,后边会介绍。

  • -r:帧率,表示每秒更新图像画面的次数,通常大于 24 肉眼就没有连贯与停顿的感觉了。

第二步:将 mp4 生成 m3u8

mkdir hls
ffmpeg -i lucene.mp4 -hls_time 10 -hls_list_size 0 -hls_segment_filename ./hls/lucene_%05d.ts ./hls/lucene.m3u8
  • -hls_time 设置每片的长度,单位为秒

  • -hls_list_size n: 保存的分片的数量,设置为 0 表示保存所有分片

  • -hls_segment_filename :段文件的名称,%05d 表示 5 位数字

    生成的效果是:将 lucene.mp4 视频文件每 10 秒生成一个 ts 文件,最后生成一个 m3u8 文件,m3u8 文件是 ts 的索引文件。

使用 VLC 打开 m3u8 文件,测试播放效果,VLC 是一款自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及 DVD、音频 CDVCD 及各类流媒体协议。(http://www.videolan.org/)

如果这里出现无法播放的情况,请将 FFmpegVLC 播放器更新到最新版本。

码率的设置

码率又叫比特率即每秒传输的 bit 数,单位为 bps(Bit Per Second),码率越大传送数据的速度越快。

码率的计算公式是:文件大小(转成 bit)/ 时长(秒)/1024 = kbps 即每秒传输千位数

例如一个 1M 的视频,它的时长是 10s,它的码率等于 1*1024*1024*8/10/1024 = 819Kbps

码率设置到多少才能达到最好,通过根据个人的经验或参考一些视频网台给出的参考,下图是优酷对码率的要求:

如果要将视频上传到优酷则必须按照上面的要求,如果是自己搭建视频服务器,码率设置不易过大,最终达到的视频清晰度满足业务需求即可。

三、播放器

0x01 技术选型

视频编码后要使用播放器对其进行解码、播放视频内容。在 web 应用中常用的播放器有 flash 播放器、H5 播放器或浏览器插件播放器,其中以 flashH5 播放器最常见。

flash 播放器:缺点是需要在客户机安装 Adobe Flash Player 播放器,优点是 flash 播放器已经很成熟了,并且浏览器对 flash 支持也很好。

H5播放器:基于 h5 自带 video 标签进行构建,优点是大部分浏览器支持 H5,不用再安装第三方的flash 播放器,并且随着前端技术的发展,h5 技术会越来越成熟。

本项目采用H5播放器,使用 Video.js 开源播放器。

Video.js 是一款基于 HTML5 世界的网络视频播放器。它支持 HTML5Flash 视频,它支持在台式机和移动设备上播放视频。这个项目于 2010 年中开始,目前已在 40 万网站使用。

官方地址:http://videojs.com/

0x02 下载 video.js

Video.js: https://github.com/videojs/video.js

videojs-contrib-hls: https://github.com/videojs/videojs-contrib-hls#installation(videojs-contrib-hls是播放 hls 的一个插件)

使用文档:http://docs.videojs.com/tutorial-videojs_.html

本教程使用 video.js 6.7.3 版本,videojs-contrib-hls 5.14.1 版本。

下载上边两个文件,为了测试需求将其放在门户工程的 plugins 目录中。

0x03 搭建媒体播放器

正常使用 video.js 播放视频是通过一个网页,用户通过浏览器打开网页去播放视频,网页和视频都从web服务器请求,通常视频的 url 地址使用单独的域名。

配置 Nginx媒体服务器

HLS 协议基于 Http 协议,本项目使用 Nginx 作为视频服务器。下图是 Nginx 媒体服务器的配置流程图:

1、用户打开www.xuecheng.com上边的 video.html 网页 ,在此网页中引入视频链接,视频地址指向video.xuecheng.com

2、video.xuecheng.com 进行负载均衡处理,将视频请求转发到媒体服务器

根据上边的流程,我们在媒体服务器上安装 Nginx,并配置如下:

#学成网媒体服务
server {
   
    listen 90;
    server_name localhost;
    #视频目录
    location /video/ {
   
        alias F:/develop/video/;
    }
}

配置媒体服务器代理

媒体服务器不止一台,通过代理实现负载均衡功能,使用 Nginx 作为媒体服务器的代理,此代理服务器作为 video.xuecheng.com 域名服务器。

配置 video.xuecheng.com 虚拟主机:

注意:这里我们开发环境中代理服务器和媒体服务器在同一台服务器,使用同一个Nginx

#学成网媒体服务代理
map $http_origin $origin_list{
   
    default http://www.xuecheng.com;
    "~http://www.xuecheng.com" http://www.xuecheng.com;
    "~http://ucenter.xuecheng.com" http://ucenter.xuecheng.com;
} 
#学成网媒体服务代理
server {
   
    listen 80;
    server_name video.xuecheng.com;
    location /video {
   
        proxy_pass http://video_server_pool;
        add_header Access-Control-Allow-Origin $origin_list;
        #add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Methods GET;
    }
}

cors跨域参数:

  • Access-Control-Allow-Origin:允许跨域访问的外域地址

  • Access-Control-Allow-Credentials: 允许客户端携带证书访问

  • Access-Control-Allow-Methods:允许客户端跨域访问的方法

通常允许跨域访问的站点不是一个,所以这里用 map 定义了多个站点。

如果允许任何站点跨域访问则设置为 *,通常这是不建议的。

video_server_pool 的配置如下:

#媒体服务
upstream video_server_pool{
   
    server 127.0.0.1:90 weight=10;
}

配置 hosts 文件,本教程开发环境使用 Windows10,修改 hosts 文件,路径为 C:\Windows\System32\drivers\etc\hosts

127.0.0.1 video.xuecheng.com

0x04 测试 video.js

参考文档如下:

https://github.com/videojs/videojs-contrib-hls#installation

http://jsbin.com/vokipos/8/edit?html,output

1、编写测试页面 video.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <title>视频播放</title>
        <link href="/plugins/videojs/video-js.css" rel="stylesheet">
    </head>
    <body>
        <video id=example-video width=800 height=600 class="video-js vjs-default-skin vjs-big-play-
                                                            centered" controls poster="http://127.0.0.1:90/video/add.jpg">
            <source
                    src="http://video.xuecheng.com/video/hls/lucene.m3u8"
                    type="application/x-mpegURL">
        </video>
        <input type="button" onClick="switchvideo()" value="switch"/>
        <script src="/plugins/videojs/video.js"></script>
        <script src="/plugins/videojs/videojs-contrib-hls.js"></script>
        <script>
            var player = videojs('example-video');
            //player.play();
            //切换视频
            function switchvideo(){
    
                player.src({
    
                    src: 'http://video.xuecheng.com/video/hls/lucene.m3u8',
                    type: 'application/x-mpegURL',
                    withCredentials: true
                });
                player.play();
            }
        </script>
    </body>
</html>

2、测试

点击 switch 测试切换视频功能。

四、搭建学习中心前端

0x01 界面原型

先看一下界面原型,如下图,最终的目标是在此页面使用 video.js 播放视频。

0x02 创建学习中心工程

学习中心的用户是学生,为了便于系统维护和扩展,单独创建学习中心工程:

1、从资料目录拷贝 xc-ui-pc-leanring.zip 并解压到 xc-ui-pc-leanring 目录。

2、使用 webstorm 创建打开 xc-ui-pc-leanring 目录

3、进入 xc-ui-pc-leanring 目录,执行 cnpm install,将根据 package.json 的依赖配置远程下载依赖的 js 包。

创建完成,xc-ui-pc-leanring工程如下:

配置域名

学习中心的二级域名为 ucenter.xuecheng.com,我们在 nginx 中配置 ucenter 虚拟主机。

#学成网用户中心
server {
   
    listen 80;
    server_name ucenter.xuecheng.com;
    #个人中心
    location / {
   
        proxy_pass http://ucenter_server_pool;
    }
} 
#前端ucenter
upstream ucenter_server_pool{
   
    #server 127.0.0.1:7081 weight=10;
    server 127.0.0.1:13000 weight=10;
}

在根服务下添加一个 /plugins/ 站点

# 根服务
server{
   
    listen       80;
    server_name  www.xuecheng.com;
    ssi on;
    ssi_silent_errors on;
    location /plugins/ {
         
        # 跨域参数
        alias  E:/Project/XueChengOnline/xcEduUI01/xc-ui-pc-static-portal/plugins/;   
        add_header Access-Control-Allow-Origin http://ucenter.xuecheng.com; 
        add_header Access-Control-Allow-Credentials true;          
        add_header Access-Control-Allow-Methods GET;        
    }
    .....
}

访问测试

启动工程,看到下边的界面说明本工程创建完成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AtcW0UdA-1595567116697)(https://qnoss.codeyee.com/20200704_13/image16)]

0x03 调试视频播放页面

使用 vue-video-player 组件将 video.js 集成到 vue.js 中,本项目使用 vue-video-player实现video.js 播放。

组件地址:https://github.com/surmon-china/vue-video-player

上面的 xc-ui-pc-learning 工程已经添加 vue-video-player 组件,我们在 vue 页面直接使用即可。

前边我们已经测试通过 video.js,下面我们直接在 vue 页面中使用 vue-video-player 完成视频播放。

导入 learning_video.vue 页面到 course 模块下。

配置路由

import learning_video from '@/module/course/page/learning_video.vue';
{
   
    path: '/learning/:courseId/:chapter',
    component: learning_video,
    name: '录播视频学习',
    hidden: false,
    iconCls: 'el‐icon‐document'
}

预览效果

请求:http://ucenter.xuecheng.com/#/learning/1/2

第一个参数:courseId,课程id,这里是测试页面效果随便输入一个 ID 即可,这里输入1

第二个参数:chapter,课程计划id,这里是测试页面效果随便输入一个 ID 即可,这里输入2

五、媒资管理

前边章节完成在线视频播放,如何实现点击课程计划播放视频呢,课程视频如何管理呢?

本节开始将对课程视频进行管理。

0x01 需求分析

媒资管理系统是每个在线教育平台所必须具备的,百度百科对它的定义如下:

每个教学机构都可以在媒资系统管理自己的教学资源,包括:视频、教案等文件。

目前媒资管理的主要管理对象是课程录播视频,包括:媒资文件的查询、视频上传、视频删除、视频处理等。

  • 媒资查询:教学机构查询自己所拥有的媒体文件。

  • 视频上传:将用户线下录制的教学视频上传到媒资系统。

  • 视频处理:视频上传成功,系统自动对视频进行编码处理。

  • 视频删除 :如果该视频已不再使用,可以从媒资系统删除。

下边是媒资系统与其它系统的交互情况:

1、上传媒资文件

前端/客户端请求媒资系统上传文件。

文件上传成功将文件存储到媒资服务器,将文件信息存储到数据库。

2、使用媒资

课程管理请求媒资系统查询媒资信息,将课程计划与媒资信息对应、存储。

3、视频播放

用户进入学习中心请求学习服务学习在线播放视频。

学习服务校验用户资格通过后请求媒资系统获取视频地址。

0x02 开发环境搭建

创建媒资数据库

1、媒资文件信息

package com.xuecheng.framework.domain.media;

import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;

@Data
@ToString
@Document(collection = "media_file")
public class MediaFile {
   
    /*
    文件id、名称、大小、文件类型、文件状态(未上传、上传完成、上传失败)、上传时间、视频处理方式、视频处理状态、hls_m3u8,hls_ts_list、课程视频信息(课程id、章节id)
     */
    @Id
    //文件id
    private String fileId;
    //文件名称
    private String fileName;
    //文件原始名称
    private String fileOriginalName;
    //文件路径
    private String filePath;
    //文件url
    private String fileUrl;
    //文件类型
    private String fileType;
    //mimetype
    private String mimeType;
    //文件大小
    private Long fileSize;
    //文件状态
    private String fileStatus;
    //上传时间
    private Date uploadTime;
    //处理状态
    private String processStatus;
    //hls处理
    private MediaFileProcess_m3u8 mediaFileProcess_m3u8;

    //tag标签用于查询
    private String tag;

}

2、创建 xc_media 数据库

媒资系统使用 mongodb 数据库存储媒资信息,再创建集合 media_file

创建媒资服务工程

媒资管理的相关功能单独在媒资服务中开发,下边创建媒资服务工程(xc-service-manage-media)。
媒资服务的配置与 cms 类似,导入 资料/xc-service-manage-media 工程,工程结构如下:

0x03 上传文件

断点续传解决方案

通常视频文件都比较大,所以对于媒资系统上传文件的需求要满足大文件 的上传要求。http 协议本身对上传文件大小没有限制,但是客户的网络环境质量、电脑硬件环境等参差不齐,如果一个大文件快上传完了网断了,电断了没有上传完成,需要客户重新上传,这是致命的,所以对于大文件上传的要求最基本的是断点续传。

什么是断点续传?

引用百度百科:断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载,断点续传可以提高节省操作时间,提高用户体验性。

如下图:

上传流程如下:

1、上传前先把文件分成块

2、一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传

3、各分块上传完成最后合并文件

文件下载则同理。

文件分块与合并

为了更好的理解文件分块上传的原理,下边用java代码测试文件的分块与合并。

1、分块

文件分块的流程如下:

1、获取源文件长度

2、根据设定的分块文件的大小计算出块数

3、从源文件读数据,再依次向每一个块文件写入数据。

单元测试代码如下

/**
     * 测试文件分块
     */
@Test
public void testChunk() throws IOException 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值