拉取srs镜像并实例化为容器
我这里用的是第5版srs。
在本机用管理员权限打开PowerShell(Windows+X会弹出选项框,选择对应的选项即可)
在PowerShell中输入
docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 ossrs/srs:5
显示说Unable to find image 'ossrs/srs:5' locally,就是说没有在本机找到这个镜像,于是下一行开始自动pull这个镜像。此时,屏幕上会输出若干日志。打开docker的container->Logs,发现他俩的日志一样的,这就说明这个镜像已经实例化成为容器并且正在运行中。
根据网上教程重新拉取了一个镜像,执行下面的语句,给container命名为srs5.0,并运行
docker run -it --name srs5.0 -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 10080:10080/udp registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5
打开docker,发现刚才拉取的镜像和实例化的容器已经在正常运行了。红框中前面是--name后面的参数,蓝色链接就是用来实例化容器的镜像地址
用docker安装并启动ffmpeg
但是报错:
打开Ubuntu,输入如下命令,查看所有的ffmpeg镜像
拉取ffmpeg镜像
看到第一个linuxserver星最多,果断选择这个镜像来拉取。在Ubuntu里输入下面的命令:
docker pull linuxserver/ffmpeg
我也不知道为啥它给我整了两个pulling我啥都没干啊...Anyway,我们继续。接着输入下面的命令来查看本地都有哪些镜像。
docker image ls
可以看到第一个就是我们刚刚拉取的ffmpeg镜像,然后最下面的就是根据新教程拉取的srs镜像。
ffmpeg容器被创建但未运行
接下来按照我们之前对srs镜像的处理方法,执行如下命令,将该镜像实例化成容器并给它命名为ffmpeg,并运行
docker run -it --name ffmpeg -p 8066:8066 linuxserver/ffmpeg:latest
此后,我打开docker desktop看了一下,确实有这个容器了,但是并没有运行起来。在Ubuntu里输入docker ps以查看所有运行中的容器,也没有出现新实例化的fmpeg,很郁闷。
关注到了在Ubuntu和docker desktop日志里的同样的提示:
斗胆在Ubuntu里尝试运行一下它说的那个man ffmpeg
额......不管了,先去睡一觉再说。遇到困难睡大觉!!!
起床并继续干活!
在网上查了一下ffmpeg的docker容器一启动就关闭的原因,找到一条比较符合我情况的解释:docker容器运行必须有一个前台进程, 如果没有前台进程执行,容器认为空闲,就会自行退出。
ffmpeg是一个对视频进行编解码等一系列操作的软件。也就是说,当ffmpeg没有处理视频的任务时,容器就会退出。所以,现在应该做的是学习如何使用ffmpeg将视频推流到srs服务器上去。
重新拉取srs镜像并实例化为容器并尝试推流
打开srs官网,按指示输入命令:
docker run --rm -it ossrs/srs:encoder ffmpeg -stream_loop -l -re -i doc/source.flv -c copy -f flv rtmp://host.docker.internal/live/livestream
推流参数报错(stream_loop)
再次拉取一个新镜像并实例化为容器。应该去查一下如何将启动已有容器和用ffmpeg推流的命令结合起来。。。
可以看到最后报错说:错误信息“Expected number for stream_loop but found: -l”表明ffmpeg期望一个数字作为stream_loop的参数,但却找到了“-l”这个标志。
ffmpeg的-stream_loop
标志用于指定输入流的循环次数。这个参数应该后面跟着一个数字,表示循环的次数。但在你的问题中,看起来你在-stream_loop
后面跟了一个“-l”,而不是一个数字。
解决参数报错的问题
因此,需要检查ffmpeg命令,并确保-stream_loop
后面跟的是一个数字,而不是“-l”。
如果想让输入流循环播放5次,命令应该是这样的:
ffmpeg -re -i 1.mp4 -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp -stream_loop 5 rtsp://192.168.79.133/live/room
重新输入:
查了一下报错原因:docker没有暴露在某个端口上或者若干原因。我打开docker看了一下,新拉取的tag为encode镜像并没有创建对应的容器,没有在运行。所以是因为该容器不存在导致的问题。于是我斗胆更改了一下命令,希望启动已有的容器:
docker run linuxserver/ffmpeg:latest ffmpeg -stream_loop 5 -re -i doc/source.flv -c copy -f flv rtmp://host.docker.internal/live/livestream
此时,docker desktop上根据已有镜像新创建了容器。最下面那个就是
Ubuntu里显示:
啊我非常的满意啊!虽然是error,但是就该是error。我就是想看到这个error。因为我没有在文件夹里添加任何视频文件。接下来只需要在指定文件夹里添加视频文件就可以了。红框里的是添加好的视频的路径。试着改了一下启动容器的命令,发现出了问题。
出现问题:ffmpeg容器一启动就关闭
问了一下文心一言,它意思没啥问题。此外,我们还能够明确,第二个ffmpeg开始,往后的命令是独立的一部分,前面的就是单纯地启动容器。但是好像也有点区别,因为如果指只输入docekr start ffmpeg的话,容器会运行(虽然一运行就关闭,但是最起码没有报错)
重来一遍:先启动srs,再启动ffmpeg,再输入ffmpeg命令。
好好好,还是不行,非要我安装一个ffmpeg。呵,我就不。
出现报错:找不到文件
重新拉取了一个ffmpeg镜像,实例化为容器并进行推流
docker run -it --name ffmpeg_new -p 8066:8066 jrottenberg/ffmpeg ffmpeg -stream_loop 1 -re -i E://a_Junior/Internet协议与设计/ffmpeg_video/firework.mp4 -c copy -f flv rtmp
://host.docker.internal/live/livestream
又做了多次尝试,结果都是报错:没有找到这个文件。文心一言给出的解释是路径输入风格有问题,我又做了尝试,没用。探索过后发觉,在Windows系统的目录下的文件应该首先被cd到Linux的目录下。但是由于二者的语法构成不同,因此WSL提供专门为此服务的工具。
用WSL的工具将Windows的文件cd到Linux中
编写脚本实现转换
将如下代码写在win2linux_path.sh的脚本中
# usage: bash win2linux_path.sh "C:\Users\asus\Anaconda3"
win_path=$1 # 脚本的第一个参数就是windows路径
#win_path="C:\Users\asus\Anaconda3" # 一个示例路径
tmp_path=${win_path/:/} # 将冒号删掉
tmp_path=${tmp_path//\\/\/} # 将\\替换为/
disk_id=${tmp_path:0:1} # 取出第一个字母,也就是C盘的C,冒号后面第一个0指的是从下标为0的地方开始提取,第二个冒号后面的1表示提取一个字母
disk_id=$(echo $disk_id | tr [:upper:] [:lower:]) # 大写转小写
#echo $disk_id
other_path=${tmp_path:1} # 路径中除了磁盘以外的部分
linux_path="/mnt/"${disk_id}${other_path} # 需要将/mnt/接在路径最前方
echo "windows path is "${win_path}
echo "linux path is "${linux_path}
输入windows里的路径执行之后得到Linux的路径格式。此处参考Windows路径转成Linux子系统的路径_windows路径和linux路径变换-CSDN博客
将转换完的路径输入ffmpeg推流命令
将启动容器和推流命令分开输入之后回到了ffmpeg瞬间启动和关闭导致的无法识别ffmpeg命令的问题上来。
解决ffmpeg启动后瞬间关闭的问题
按如下命令新实例化一个容器
docker run -it --entrypoint='bash' jrottenberg/ffmpeg
重点在于--entrypoint='bash'上,是创建一个容器用于终端登录。完成之后看一下其状态:特别好,最下面那个就是,已经运行起来了。
希望其在停止后开始就用最普通的start命令。用下面的命令,在容器开启之后重新进入这个终端
docker attach <container_name>
执行结果如下图,
文件不存在的问题仍未解决
请教了学过Linux的舍友,舍友说可以从Linux文件夹中查看磁盘文件。不需要再进行文件剪切之类的移植操作。于是打开了Ubuntu文件夹,在mnt里果然找到了下图内容。但是说无法访问,可能没有权限使用网络资源。无所谓,我有gpt。
从Windows系统打开想访问的文件夹的属性->共享
啊,可以看到下面图片说它这个盘是不共享的,那我们就给它改成共享的
点击高级共享,勾选:“共享此文件夹”
完事之后,就可以看到这个文件夹变成“共享式”的了
然后再回到Ubuntu,访问E盘。
我去?还不行??报错还是一样的。无碍,再战!
再回到高级共享页面,点击“权限”,出现下图界面。勾选所有选项框,我之前是只有后两个勾选上了,就把第一个也勾上了。然后确定。
解决找不到文件的问题
由于是在ffmpeg容器里使用视频文件,因此需要将windows中的文件夹挂载在docker中。挂载方法:docker提供一个叫数据卷的东西。数据卷:“其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的”。感觉像是由一个容器定义的一个数据挂载信息。其他的容器启动可以直接挂载数据卷容器中定义的挂载信息。操作起来就是随笔用一个镜像实例化一个新的容器,然后在该语句中执行/本地路径/文件夹:/需要挂载的路径 的操作。代码如下:
docker run -it -v /mnt/e/fire:/usr/Downloads --name dataVol jrottenberg/ffmpeg
上述代码的意思就是:用jrottenberg/ffmpeg镜像实例化一个名字是dataVol的容器,并且完成文件夹从本地到docker路径的挂载,并运行该容器。该容器就是所谓“数据卷”
之后,再新建一个容器来使用这个数据卷,命令如下:
docker run -it --volumes-from dataVol jrottenberg/ffmpeg
其中,--volums-from后面跟的就是需要再该容器中使用的数据卷(容器)的名称,剩下的语法都何前文类似,不做解释。
需要注意的是,如果实例化该容器的镜像为ffmpeg,就有可能出现一启动就关闭的情况(如前文的情况),因此需要修改一下创建语句:
docker run -it --entrypoint='bash' --volumes-from dataVol jrottenberg/ffmpeg
为了验证挂载和使用是否成功,进行如下操作:
首先运行并进入最后创建的容器
然后用cd /需要挂载的路径,查看是否成功
cd /usr/Downloads
成功之后再使用“ls”查看该文件夹下的所有文件。此时就能看到需要操作的文件了。
接下来就在这个容器中进行ffmpeg的推拉流操作,即可。
下一篇讲述如何真正使用ffmpeg进行推流。