Generally speaking, the video displayed on the web page is transmitted from the back end to the front end. Then, how does the back end complete the operation of video transmission? Let’s take the node back end as an example, and choose Express as the server framework

Our catalog is as follows:

  • Node_modules:Depend on the package
  • Service:Processing front-end requests
  • The view:Front-end HTML interface file
  • Video:Video file
  • Index. Js:Entrance to the file

Basic configuration

  1. Open the entry fileindex.js, write the following code:
const express = require('express')
const path = require('path')
const router = require('./service/video')

const app = express()

app.use(router);

app.use(express.static(path.resolve(__dirname, './view')))
app.use(express.static(path.resolve(__dirname, './video')))


app.listen(8000.() = > {
    console.log('The server runs at: http://127.0.0.1:8000');
})
Copy the code
  1. Create a new file under servicevideo.js, the contents are as follows:
const router = require('express').Router();
const fs = require('fs')
const path = require('path')


module.exports = router;
Copy the code
  1. Create a new file under viewindex.html, the contents are as follows:
<! DOCTYPEhtml>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        #video {
            width: 800px;
        }
    </style>
</head>

<body>
    <video id="video" src="/test.mp4" controls></video>
</body>

</html>
Copy the code
  1. Pick up any video file and put it invideoFolder, here withtest.mp4As an example

Normal delivery

Static introduced

If we have completed the basic configuration, we can open the command line terminal at the root of the project and type node index.js to see the following:

PS C:\Users\wangyue\Desktop\ Video stream > node.\ index.js server running at: http://127.0.0.1:8000Copy the code

At this point, we open the browser, enter http://127.0.0.1:8000 in the address bar, we can see our front interface, and can play the video normally

In the basic configuration, the SRC of the video is written as /test.mp4, which is imported directly as a static file


The overall transfer

  1. Open the service foldervideo.js, add a new request route as follows:
const router = require('express').Router();
const fs = require('fs')
const path = require('path')
// -------------------------
// Overall delivery
router.get('/demo1'.(req, res) = > {

    let videoPath = path.resolve(__dirname, '.. /video/test.mp4')

    fs.readFile(videoPath, (err, data) = > {
        if (err) throwerr; res.send(data); })})// -------------------------
module.exports = router;
Copy the code
  1. Modify theindex.htmlThe video path
<video id="video" src="/demo1" controls></video>
Copy the code

Restart the server, refresh the browser, and you’ll see that the video is delivered and playing properly

Disadvantages:

  • If the video file is very large, the speed of video transfer from the background to the front end will be very slow in the case of low network bandwidth
  • The front end needs to receive all the video data before playing

The Stream transmission

We can use FS Stream to achieve streaming video reading and streaming transmission

  1. Open the service foldervideo.js, add a new request route as follows:
const router = require('express').Router();
const fs = require('fs')
const path = require('path')
// -------------------------
/ / the Stream transmission
router.get('/demo2'.(req, res) = > {

    let videoPath = path.resolve(__dirname, '.. /video/test.mp4')

    let readStream = fs.createReadStream(videoPath)

    readStream.pipe(res);

})

// -------------------------
module.exports = router;
Copy the code
  1. Modify theindex.htmlThe video path
<video id="video" src="/demo1" controls></video>
Copy the code

Restart the server, refresh the browser, and you’ll see that the video is delivered and playing properly

Disadvantages:

  • Can’t demand

Slice passing

Slice passing, as the name suggests, is to cut the original video into small videos, and the browser side only requests one small video at a time, instead of having to send a complete video to the request.

Advantages:

  • Fast transmission speed
  • Support on demand
  • Can dynamically switch different resolution
  • Saves traffic and network bandwidth

Video slice delivery relies on streaming media transmission protocol. Common streaming media transmission protocols are as follows:

  1. rtp
  2. rtcp
  3. rtsp
  4. rtmp
  5. mms
  6. flv
  7. hls

This article mainly describes how to use HLS protocol for video slice transmission, other protocols are similar, interested to explore.

Summary of HLS

HTTP Live Streaming (HLS) is a Streaming media network transmission protocol based on HTTP. The working principle is to split the video file into a short, orderly small file, the browser side through a special.m3U8 index file to request the video, and only request a small file, do not need to request a complete video file.

In human speaking, a large video is cut into small videos, and the name and order of the small videos are recorded in a small book. The browser sends requests against the records listed in the small book.

For example, if the total duration of test.mp3 is 60 seconds, we can split it into 12 videos, each of which is 5 seconds long

Test.mp3 => [test1.mp3, test2.mp3, testn.mp3, ···, test12.mp3]Copy the code

Our little notebook. M3u8 contains

test1.mp3 00:01~05:00
test2.mp3 05:01~10:00
test3.mp3 10:01~15:00... test12. Mp355:01~60:00
Copy the code

Then, the browser will go to.m3U8 to find the corresponding small video based on the progress of your current video, and then request it down, and then inserted into the video TAB, so that the video slice play. Typically, the browser will send the next video to the request in advance.


Sliced tools

First of all, we need to clarify the concept that HLS is a transport protocol that helps you transfer small videos over the network.

As for how you can cut a large video into n smaller videos, that’s not what HLS does, you need to use other tools to do that.

We can use FFmpeg to slice our video files, FFmpeg you can understand as a software, or command line tool, it is very powerful, can help us to video for a variety of operations, such as video compression, transfer format, extract pictures, extract audio, into the watermark and so on.

Of course, if you don’t want to use FFmpeg, you can also check out OpenCV

  • FFmpeg website
  • FFmpeg download address
  • FFmpeg Introduction tutorial

The HLS protocol is to cut our video into small videos, and these small videos are formatted with.ts

That is, assuming our original video is test.mp4, we need to convert it to test.ts first. Of course, we can also go ahead and cut the MP4 directly to TS, which we’ll talk about at the end.

Then cut the test.ts. There are two ways of cutting, cutting by slice length and cutting by slice size

Note: After you download FFmpeg, make sure to set the environment variables for it by:

  1. Open theffmpeg/binfolder
  2. Copy the address of the bin directory above the address bar in Windows Explorer. Mine isD:\ffmpeg\bin
  3. Click on theMy computer, right mouse button selectionProperties -> Advanced System Settings -> Environment Variables ->
  4. chooseAdvanced System Settings
  5. chooseThe environment variable
  6. inThe user variablesSystem variablesPathAnd double click
  7. Click on thenew
  8. Paste the path to our FFmpeg bin directory, mine isD:\ffmpeg\bin
  9. Click ok

Mp4 turn ts

Open your source video folder, hold down shift + right mouse button, select Open Powersheel here, and then type the following command from the command line terminal:

ffmpeg -y -i test.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb test.ts
Copy the code

Cutting ts

To cut ts video into small videos, we need to choose whether to cut by length or by size. After the cut is complete, we will get a.m3u8 index file

Here, it is assumed that we slice by length, each slice is 10 seconds long, the index file name is index.m3u8, and the file name format of the small video is test-n.ts

Open the folder where your TS videos are located and create a new chunk folder under the current folder to store video slices and index files

The following

Open the folder where your TS video is located, hold down the Shift + right mouse button, select Open Powersheel here, and then type the following command from the command line terminal:

ffmpeg -i test.ts -c copy -map 0 -f segment -segment_list chunk/index.m3u8 -segment_time 10 chunk/test-%04d.ts
Copy the code

After the preceding command is executed, the test.ts video is sliced in 10 seconds and an index file is generated. All slice files and index files are saved in the chunk folder


Slice transmission

After the steps above, we have the slicing and indexing files, but how do we get the front end to display our video files fully?

If we want to play HLS protocol videos, then we need a parser. The common parser is as follows:

  • video.js
  • hls.js

Videojs way

First, open our index. HTML and make the following changes

<! DOCTYPEhtml>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
	<link href="https://cdn.bootcdn.net/ajax/libs/video.js/7.10.1/video-js.min.css" rel="stylesheet">
    <title>Document</title>
    <style>
        #video {
            width: 800px;
        }
    </style>
</head>

<body>
    <! -- vjs-big-play-Centered -->
    <video id="video" class="video-js vjs-default-skin vjs-big-play-centered" controls>
        <! -- write our index file path in the source tag -->
        <source src="/chunk/index.m3u8" type="application/x-mpegURL">
    </video>

	<script src="https://cdn.bootcdn.net/ajax/libs/video.js/7.10.1/video.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/video.js/7.10.1/lang/zh-CN.min.js"></script>

    <script>
        window.onload = () = > {
            videojs('video', {
                language: 'zh-CN'}); }</script>
</body>

</html>
Copy the code

Note: you need to import video.js and video.css. By default, videoJS plays in English. If you want to replace it with Chinese, you need to import a language pack and set the language

After completing the above steps, we can find that the video can play normally and support on-demand. At the same time, open the development control panel and check the network, we can see that the video is loaded by slices, which greatly improves the loading speed of our large video.


HLSJS way

It’s still time to modify our index.html

<! DOCTYPEhtml>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        #video {
            width: 800px;
        }
    </style>
</head>

<body>
    <video id="video" controls></video>

    <script src="https://cdn.bootcdn.net/ajax/libs/hls.js/1.0.0-beta.3.0.canary.6685/hls.min.js"></script>

    <script>
        window.onload = () = > {
            let video = document.getElementById('video')
            let videoSrc = '/chunk/index.m3u8';

            if (Hls.isSupported()) {
                var hls = new Hls();
                hls.loadSource(videoSrc);
                hls.attachMedia(video);
            } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoSrc; }}</script>
</body>

</html>
Copy the code

After completing the above configuration, open the browser to see the effect

Personally, I prefer to use hsS.js


other

I did this in native writing, and if you use it in vue, React, etc., the method is similar, so I won’t do the demo here.

About VideoJS and HLSJS which to see your own preferences to the line, this is mainly about the application of video streaming, so will not do too much on these two things, want to know can go to Baidu


Slice the encryption

Sometimes, if we want to encrypt our video, or if we want to encrypt our sharded video, to prevent people from stealing our video, then we can choose to encrypt our video slices

The procedure is to cut an MP4 video file into multiple TS segments, encrypt each segment with AES-128 during the cutting process, and finally generate an M3U8 video index file

Prerequisite: The computer operating system must be installedopensslGit bash comes with OpenSSL


Generate the enc. Key

In the folder where your MP4 video is, open Git bash and type the following command:

openssl rand 16 > enc.key
Copy the code

Generation iv

In the folder where your MP4 video is, open Git bash and type the following command:

openssl rand -hex 16
Copy the code

When you execute the above command, you get a string of characters. Write it down or copy it down


New enc. Keyinfo

In the folder where your MP4 video is, create a new file called enc.keyinfo and the contents are as follows

http://127.0.0.1:8000/enc.key C: \ Users \ wangyue \ Desktop \ video \ video \ enc key 9 a605f6be42059d689b40e13e39ff289Copy the code

The first line is the network access path for enc.key

The second line is the local absolute path to enc.key

The third line is the IV string we got in step 2


Encryption section

In the folder where your MP4 video is located, open the command line terminal and type the following command:

ffmpeg -y -i .\test.mp4 -hls_time 10 -hls_key_info_file .\enc.keyinfo -hls_playlist_type vod -hls_segment_filename "./chunk/test-%d.ts" ./chunk/index.m3u8
Copy the code

The above order reads:

Slice the test.mp4 file into 10-second chunks in the current directory, encrypt it using enc. Keyinfo in the current folder, and save the slice and index files in the chunk folder

When we use HLSJS to pass the video to the front end, we can see that the video can also be displayed normally, but if you open our slice file separately, it will prompt that the file cannot be played, which realizes our video slice encryption

In the meantime, open the browser developer console, click Network, and let’s refresh the page

As you can see, the browser first requests index.m3u8, then enc.key, and then loads our video slice

The new guy might be wondering, now that our slices are encrypted, how do we decrypt them in the browser?

You don’t have to worry about this, HLSJS or VideoJS will automatically decrypt it for you, based on your enc.key


other

The above encryption, in fact, is not very rigorous, we can know that when the page loads, it will request our enc.key through XHR

We can still restrict this request, such as determining if the user is logged in, and not returning the enc.key if not