Docker nginx容器代理播放m3u8视频文件(HLS)

news2024/10/1 3:27:01

文章目录

  • Docker Nginx容器代理播放M3U8文件教程
    • 获取Nginx Docker镜像
    • 设置Nginx配置文件
    • 用 ffmpeg 将 MP4 文件转换成 m3u8 文件
    • 运行Docker容器
    • 测试M3U8流
    • 其他问题
      • 我用vlc都能播放http://192.168.121.50/forest4kTest.m3u8和http://192.168.121.50/forest4kTest.mp4,那还要m3u8做什么,直接播放视频文件不就行了吗?

Docker Nginx容器代理播放M3U8文件教程

本教程将介绍如何在Docker中使用Nginx作为反向代理,以播放M3U8文件。我们会通过步骤详细解释每个过程,并提供命令和代码示例。

获取Nginx Docker镜像

我们用dockerfile构建镜像:

(Dockerfile)

FROM nginx:1.18

然后用脚本构建镜像:

(build_docker_image.sh)

#!/bin/bash

# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u

# 设置变量
IMAGE_NAME="kyai_nginx_x86"
IMAGE_TAG="v1.18_20230724"

# 检查依赖
if ! [ -x "$(command -v docker)" ]; then
  echo 'Error: Docker is not installed.' >&2
  exit 1
fi

# 构建 Docker 镜像
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" .

# 查看 Docker 镜像
docker images

然后可以用脚本把镜像导出为离线包:

(docker_tar.sh)

#!/bin/bash

# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u

REPOSITORY="kyai_nginx_x86"
REP_TAG="v1.18_20230724"

DOCKER_TAR="${REPOSITORY}-${REP_TAG}.tar"
USER=root
################################################################################
WHO=$(whoami | grep "${USER}$")
if [ -z ${WHO} ]; then
    echo
    echo "Please change to \"${USER}\" user mode first!"
    echo
    exit 1
fi

echo "REPOSITORY: ${REPOSITORY}"
echo "REP_TAG: ${REP_TAG}"
echo "docker save -o ${DOCKER_TAR}..."
docker save -o ${DOCKER_TAR} ${REPOSITORY}:${REP_TAG}
chmod 777 $DOCKER_TAR

在这里插入图片描述

设置Nginx配置文件

在运行Nginx Docker容器之前,我们需要设置一个Nginx配置文件。此文件将定义如何处理传入的HTTP请求。

创建一个新的文件nginx.conf并输入以下内容:

worker_processes 1;

events {
    worker_connections 1024;
}

http {

    sendfile on;

    server {
        listen 80;

        location / {
            root /usr/share/nginx/html;
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }
    }
}

这个文件是一个Nginx服务器的配置文件,以下是对它的逐行解释:

  • worker_processes 1;:设置Nginx应使用的工作进程数。在大多数情况下,建议将此值设置为可用的CPU核心数。

  • events { worker_connections 1024; }:在events块中定义了每个工作进程允许的最大连接数。在这个例子中,每个工作进程允许最多1024个并发连接。

  • http { ... }http块包含了所有的HTTP相关的配置。

    • sendfile on;:启用高效的文件传输模式。当启用时,Nginx可以直接从磁盘到TCP套接字进行数据传输,而无需在用户空间复制数据。

    • server { ... }:定义了一个服务器(或虚拟主机)的配置。

      • listen 80;:该服务器监听80端口,这通常是HTTP的默认端口。

      • location / { ... }:定义了对根路径(/)的请求的处理方式。所有URL路径都匹配此位置。

        • root /usr/share/nginx/html;:定义了服务器的根目录,即所有相对URL路径的基础路径。

        • types { ... }:定义了不同文件扩展名的MIME类型。在这个例子中,.m3u8文件被标记为application/vnd.apple.mpegurl.ts文件被标记为video/mp2t

        • add_header Cache-Control no-cache;:添加一个HTTP响应头,指示客户端不要缓存响应。

        • add_header Access-Control-Allow-Origin *;:添加一个HTTP响应头,允许任何来源的跨域请求(CORS)。

这个配置文件将Nginx配置为一个简单的HTTP服务器,它可以为.m3u8和.ts文件提供服务,并禁用了响应缓存。

用 ffmpeg 将 MP4 文件转换成 m3u8 文件

假设我们有一个forest4kTest.mp4文件:

在这里插入图片描述

我们用下面命令将其转换为 m3u8 文件(我的ffmpeg版本是4.2.7-0ubuntu0.1):

ffmpeg -i forest4kTest.mp4 -codec: copy -bsf:v h264_mp4toannexb -map 0 -f segment -segment_list forest4kTest.m3u8 -segment_time 10 forest4kTest%03d.ts

在这个命令中:

  • -i forest4kTest.mp4指定输入文件。
  • -codec: copy表示不对视频进行重新编码,只是复制原始数据。
  • -bsf:v h264_mp4toannexb是一个比特流过滤器,用于将H264视频从MP4格式转换为MPEG2 TS格式,这是必需的,因为M3U8是基于TS的。
  • -map 0表示选择所有的流(例如,如果你的视频有音频和字幕)。
  • -f segment表示输出应该被分割成多个文件。
  • -segment_list output.m3u8指定输出的播放列表文件。
  • -segment_time 10表示每个TS段的最大长度(以秒为单位)。
  • forest4kTest%03d.ts是输出TS文件的名称模式。%03d将被替换为三位数的序号。

运行这个命令后,我们会得到一个名为forest4kTest.m3u8的播放列表文件,以及一系列的.ts文件。

在这里插入图片描述

我们可以用文本编辑器打开forest4kTest.m3u8看一下它里面内容:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:11
#EXTINF:10.100311,
forest4kTest000.ts
#EXTINF:10.000311,
forest4kTest001.ts
#EXTINF:10.000311,
forest4kTest002.ts
#EXTINF:10.000311,
forest4kTest003.ts
#EXTINF:10.000311,
forest4kTest004.ts
#EXTINF:10.000311,
forest4kTest005.ts
#EXTINF:10.000311,
forest4kTest006.ts
#EXTINF:10.000311,
forest4kTest007.ts
#EXTINF:10.000311,
forest4kTest008.ts
#EXTINF:10.000311,
forest4kTest009.ts
#EXTINF:0.633311,
forest4kTest010.ts
#EXT-X-ENDLIST

关于里面内容的解释,可以参考我另外一篇文章:M3u8播放列表文件(索引格式文件)、HLS(HTTP Live Streaming)协议介绍

运行Docker容器

我们需要写一个 run 容器的脚本,首先看看我的文件结构:

在这里插入图片描述

再看看我的run容器脚本:

(install.sh)

#!/bin/bash

# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u

echo -e "\033[1;33m"
echo " _           _        _ _               _            "
echo "(_)_ __  ___| |_ __ _| | |  _ __   __ _(_)_ __ __  __"
echo "| | '_ \/ __| __/ _' | | | | '_ \ / _' | | '_ \\\\ \/ /"
echo "| | | | \__ \ || (_| | | | | | | | (_| | | | | |>  < "
echo "|_|_| |_|___/\__\__,_|_|_| |_| |_|\__, |_|_| |_/_/\_\\"
echo "                                  |___/              "
echo -e "\033[0m"

USER=root
# USER_HOME=/root

# --------------------------------------------------------------------------

CONTAINER_NAME_NGINX="kyai_nginx"
TAR_NGINX="kyai_nginx_x86-v1.18_20230724.tar"
IMAGE_NAME_NGINX="kyai_nginx_x86"
TAG_NGINX="v1.18_20230724"
R_DEPLOY_PATH_NGINX="."


# 检查是否是root
WHO=$(whoami | grep "${USER}$")
if [ -z "${WHO}" ]; then
    echo
    echo "Please change to \"${USER}\" user mode first!"
    echo
    exit 1
fi

# --------------------------------------------------------------------------

# 获取脚本所在路径
SCRIPT_LOCATION=$(
    cd "$(dirname "$0")" || {
        echo "cd Failure"
        exit 1
    }
    pwd
)
# echo "SCRIPT_LOCATION = $SCRIPT_LOCATION"
chmod 777 ${SCRIPT_LOCATION} -R

# --------------------------------------------------------------------------

# Function to create container
# Arguments: $1 - Container name
#            $2 - Docker TAR filename
#            $3 - Image name
#            $4 - Image tag
#            $5 - Deploy path
#            $6 - The function to run container
function create_container {
    local CONTAINER_NAME="$1"
    local DOCKER_TAR="$2"
    local IMAGE_NAME="$3"
    local IMAGE_TAG="$4"
    local DEPLOY_PATH="$5"

    local docker_run="$6"

    # Check if container already exists
    if [[ "$(docker ps -aqf "name=^$CONTAINER_NAME$")" ]]; then
        echo "Container $CONTAINER_NAME already exists."
        read -p "Do you want to delete it? (y/n)" answer
        case ${answer:0:1} in
        y | Y)
            # Stop and remove container
            docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME
            # Check command result
            if [ $? -ne 0 ]; then
                echo "Failed to stop or remove container $CONTAINER_NAME."
                exit 1
            fi
            echo "Container $CONTAINER_NAME stopped and removed successfully."
            ;;
        *)
            return 0
            ;;
        esac
    fi

    # Check if image already exists
    if ! docker images | awk '{print $1":"$2}' | grep -q "^${IMAGE_NAME}:${IMAGE_TAG}$"; then
        # Check if Docker TAR file exists
        if [ ! -e "${DEPLOY_PATH}/${DOCKER_TAR}" ]; then
            echo "${DEPLOY_PATH}/${DOCKER_TAR} does not exist!"
            exit 1
        fi
        echo "Loading Docker image from ${DOCKER_TAR}..."
        docker load -i "${DEPLOY_PATH}/${DOCKER_TAR}"
        if [ $? -ne 0 ]; then
            echo "Failed to load Docker image from ${DOCKER_TAR}!"
            exit 1
        fi
    fi
    echo "Docker image ${IMAGE_NAME}:${IMAGE_TAG} already exists."

    # run container
    $docker_run "$CONTAINER_NAME" "$DOCKER_TAR" "$IMAGE_NAME" "$IMAGE_TAG" "$DEPLOY_PATH"
    if [ $? -ne 0 ]; then
        echo "$docker_run error!"
        exit 1
    fi
}

# --------------------------------------------------------------------------

# 部署 nginx 服务

# The function to run container of nginx
# Arguments: $1 - Container name
#            $2 - Docker TAR filename
#            $3 - Image name
#            $4 - Image tag
#            $5 - Deploy path
function docker_run_nginx {
    local CONTAINER_NAME="$1"
    local DOCKER_TAR="$2"
    local IMAGE_NAME="$3"
    local IMAGE_TAG="$4"
    local DEPLOY_PATH="$5"

    docker run -d \
        --restart=always \
        -p 80:80 \
        -v $SCRIPT_LOCATION/$R_DEPLOY_PATH_NGINX/mount/m3u8/files:/usr/share/nginx/html \
        -v $SCRIPT_LOCATION/$R_DEPLOY_PATH_NGINX/mount/conf/nginx.conf:/etc/nginx/nginx.conf \
        --name $CONTAINER_NAME \
        $IMAGE_NAME:$IMAGE_TAG

    # -v $SCRIPT_LOCATION/$R_DEPLOY_PATH_NGINX/../web/html/web:/ky/java/nginx/html/web \

    if [ $? -ne 0 ]; then
        echo "docker run $CONTAINER_NAME error!"
        exit 1
    fi
    echo "docker run $CONTAINER_NAME [$IMAGE_NAME:$IMAGE_TAG] successfully."
}

create_container "$CONTAINER_NAME_NGINX" "$TAR_NGINX" "$IMAGE_NAME_NGINX" "$TAG_NGINX" "$SCRIPT_LOCATION/$R_DEPLOY_PATH_NGINX" docker_run_nginx
if [ $? -ne 0 ]; then
    echo "Container $CONTAINER_NAME_NGINX create failed."
    exit 1
fi

echo
echo "$CONTAINER_NAME_NGINX deploy successfully"
echo

这个脚本将启动一个新的Docker容器,并映射主机的80端口到容器的80端口。

运行脚本后,我们可以看到如下结果:

在这里插入图片描述

测试M3U8流

可以通过访问http://localhost:80/yourfile.m3u8http://ipaddress:80/yourfile.m3u8来播放m3u8文件(80端口也可以省略掉)。

比如,我在windows上用VLC打开http://192.168.121.50/forest4kTest.m3u8(其中192.168.121.50是我Net模式虚拟机的ip地址):

在这里插入图片描述
在这里插入图片描述

m3u8视频流能被播放出来。

其他问题

我用vlc都能播放http://192.168.121.50/forest4kTest.m3u8和http://192.168.121.50/forest4kTest.mp4,那还要m3u8做什么,直接播放视频文件不就行了吗?

确实,使用直接的视频链接(如.mp4文件)可以在许多情况下播放视频。然而,M3U8作为HTTP Live Streaming(HLS)协议的一部分,提供了许多其他优势和高级功能,包括:

  1. 自适应流媒体:M3U8允许提供不同质量和分辨率的视频流,以适应各种网络条件和设备能力。客户端可以在播放过程中无缝切换不同质量的流,以优化用户体验。

  2. 实时或点播流:M3U8可以用于实时的流媒体广播,也可以用于点播内容。

  3. 容错性:由于M3U8将媒体内容分割成多个小段,所以即使在下载过程中出现问题,也只会影响到当前的段,而不是整个视频。

  4. 加密:M3U8支持对媒体段进行AES-128或SAMPLE-AES加密,以保护内容安全。

  5. 跨平台和广泛支持:M3U8和HLS协议被广泛地支持,在各种设备和平台上都可以播放,包括iOS、Android、Windows、macOS等。

因此,虽然在某些情况下,直接链接到视频文件可能更简单,但使用M3U8和HLS协议可以提供更强大和灵活的流媒体解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何安装和使用夜神模拟器连接Android Studio

目录 简介 一、安装 二、使用 三、更多资源 简介 夜神模拟器是一款在Windows平台上运行的Android模拟器软件。它能够模拟Android操作系统环境&#xff0c;让用户在电脑上轻松体验Android应用程序。夜神模拟器的功能强大&#xff0c;可以满足各种需求&#xff0c;无论是娱乐…

QT----Visual stdio翻金币案例,附源码

历经一个月&#xff0c;各种事情磕磕绊绊&#xff0c;终于结束了&#xff0c;自己还是太菜了 案例的文档写的教程已经很详细&#xff0c;这边主要是记录一些问题 github代码 gitee代码 1、图片无法加载 一开始加载首页图片和标题出不来&#xff0c;结果是paintEvent重写的字打…

【LMM 014】NExT-GPT:能够输入和生成任意模态的多模态大模型

论文标题&#xff1a;NExT-GPT:Any-to-Any Multimodal Large Language Model 论文作者&#xff1a;Shengqiong Wu, Hao Fei*, Leigang Qu, Wei Ji, Tat-Seng Chua 作者单位&#xff1a; NExT Lab, National University of Singapore 论文原文&#xff1a;https://arxiv.org/abs…

线性代数 --- 为什么LU分解中L矩阵的行列式一定等于正负1?

以下是关于下三角矩阵L的行列式一定等于-1的一些说明 笔者的一些话(写在最前面)&#xff1a; 这是一篇小文&#xff0c;是我写的关于求解矩阵行列式的一篇文章中的一部分。之所以把这一段专门提溜出来&#xff0c;是因为这一段相对于原文是可以完全独立的&#xff0c;也是因为我…

RocketMQ 投递消息方式以及消息体结构分析:Message、MessageQueueSelector

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…

条件竞争之文件上传

一、条件竞争介绍 条件竞争,在程序员日常的Web应用开发中&#xff0c;通常不如其他漏洞受到的关注度高。因为普遍的共识是&#xff0c;条件竞争是不可靠的&#xff0c;大多数时候只能靠代码审计来识别发现&#xff0c;而依赖现有的工具或技术很难在黑盒灰盒中识别并进行攻击。…

精进单元测试技能 —— Pytest断言的艺术!

本篇文章主要是阐述Pytest在断言方面的应用。让大家能够了解和掌握Pytest针对断言设计了多种功能以适应在不同测试场景上使用。 了解断言的基础 在Pytest中&#xff0c;断言是通过 assert 语句来实现的。简单的断言通常用于验证预期值和实际值是否相等&#xff0c;例如&#…

小游戏实战丨基于PyGame的消消乐小游戏

文章目录 写在前面PyGame消消乐注意事项系列文章写在后面 写在前面 本期内容&#xff1a;基于pygame实现喜羊羊与灰太狼版消消乐小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700193 实验环境 python3.11及以上pycharmpygame 安装pygame…

ENVI 各版本安装指南

ENVI下载链接 https://pan.baidu.com/s/1APpjHHSsrXMaCcJUQGmFBA?pwd0531 1.鼠标右击【ENVI 5.6(64bit&#xff09;】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;选择【解压到 ENVI 5.6(64bit&#xff09;】。 2.打开解压后的文件夹&#xff0c…

一些想法:关于行人检测与重识别OIMLoss

本文主要是介绍我们录用于 ECCV18 的一个工作&#xff1a;Person Search via A Mask-guided Two-stream CNN Model. 这篇文章着眼于 Person Search 这个任务&#xff0c;即同时考虑行人检测&#xff08;Pedestrian Detection&#xff09;与行人重识别&#xff08;Person Re-ide…

2024PMP考试新考纲-【人员领域】近期典型真题和超详细解析(5)

今天华研荟继续为您分享PMP新考纲下的【人员People领域】近年真题&#xff0c;帮助大家举一反三&#xff0c;一次性通过2024年的PMP考试。 2024年PMP考试新考纲-【人员领域】真题解析21 题&#xff1a;项目经理正在为一个项目工作。该项目由于人员流动&#xff0c;相关方登记册…

Matlab二维绘图

低级绘图命令line 有什么点就点哪里&#xff0c;然后连起来&#xff0c;没什么细节&#xff0c;不光滑&#xff0c;所以基本不会用到。 x0:0.2*pi:2*pi; ysin(x); line(x,y);%画一条sin函数线 line([-5,5],[2,2]);%画一条水平线 line([5,5],[0,2]);%画一条竖线 高级绘图命令…

MySQL之视图外连接、内连接和子查询的使用

一、视图 1.1 含义 虚拟表&#xff0c;和普通表一样使用 1.2 操作 创建视图 create view 视图名 as 修改视图 方式一&#xff1a; create or replace view 视图名 as 【查看视图相关字段】 方式二&#xff1a; alter view 视图名 as 【查看的SQL语句】 查看视图 方式一&…

BUUCTF--actf_2019_babyheap1

这题看名字就知道是堆题&#xff0c;先看保护&#xff1a; 保护除了PIE全开&#xff0c;黑盒测试&#xff1a; 题目提供增删查&#xff0c;没有改。看看IDA中代码逻辑&#xff1a; 逻辑跟我前面做的一题极为相似&#xff0c;就不过多分析。 这是free&#xff1a; 因为题目不能…

基于SSM的驾校考试预约管理设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

求两个数之间的最小公约数

目录 前言 方法&#xff1a;求两个数之间的最小公约数 1.欧几里得算法 2.枚举法 3.公共因子积 4.更相减损术 5.Stein算法 解题&#xff1a;在链表中插入最大公约数 总结 前言 今天刷每日一题&#xff1a;2807. 在链表中插入最大公约数 - 力扣&#xff08;LeetCode&#xff09;…

数据库攻防学习之MySQL

MySQL 0x01mysql学习 MySQL 是瑞典的MySQL AB公司开发的一个可用于各种流行操作系统平台的关系数据库系统&#xff0c;它具有客户机/服务器体系结构的分布式数据库管理系统。可以免费使用使用&#xff0c;用的人数很多。 0x02环境搭建 这里演示用&#xff0c;phpstudy搭建的…

SpringBoot 如何 返回页面

背景 RestController ResponseBody Controller Controller中的方法无法返回jsp页面&#xff0c;或者html&#xff0c;配置的视图解析器 InternalResourceViewResolver不起作用&#xff0c;返回的内容就是Return 里的内容。 Mapping ResponseBody 也会出现同样的问题。 解…

2024年阿里云优惠活动清单_优惠代金券领取大全

阿里云服务器优惠活动大全包括&#xff1a;云服务器新人特惠、云小站、阿里云免费中心、学生主机优惠、云服务器精选特惠、阿里云领券中心等&#xff0c;活动上阿里云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;…

Linux系统性能优化:七个实战经验

Linux系统的性能是指操作系统完成任务的有效性、稳定性和响应速度。Linux系统管理员可能经常会遇到系统不稳定、响应速度慢等问题&#xff0c;例如在Linux上搭建了一个web服务&#xff0c;经常出现网页无法打开、打开速度慢等现象&#xff0c;而遇到这些问题&#xff0c;就有人…