文章目录

  • 从B站直播间获取rtmp地址和直播码
  • 在终端使用ffpmeg进行视频或摄像头推流
  • 用python实现控制树莓派推流
  • 如何停止树莓派推流

前提条件
1、首先要有一个树莓派,并连接了摄像头,且能够访问网络。
2、在Bilibili中通过实名认证,并开通了直播间。(很简单的,实名认证通过后直接就可以开通了)。
3、FFmpeg。推流默认使用FFmpeg,树莓派官方系统默认安装FFmpeg了的,可以使用ffpmeg -version查看详细信息。

从B站直播间获取rtmp地址和直播码

申请了B站直播间后,用电脑开启直播,一定要用电脑才能获取rtmp地址和直播码,用手机直播姬开播无法获取rtmp地址和直播码。
点击开始直播后会出现rtmp地址和直播码(如下图),把rtmp地址和直播码拼接起来就是后面ffpmeg推流的地址。

在终端使用ffpmeg进行视频或摄像头推流

以下是树莓派Raspbian系统中推流命令:

#推流USB摄像头(包含音频,音频源为音频文件)
ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280720 -i “视频源” -stream_loop -1 -i “音频源” -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 10M -bufsize 10M -acodec aac -ac 2 -ar 44100 -ab 128k -f flv “推流地址”

#推流USB摄像头(包含音频,音频源麦克风)
ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280720 -i “视频源” -i “音频源” -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 10M -bufsize 10M -acodec aac -ac 2 -ar 44100 -ab 128k -f flv “推流地址”

#推流USB摄像头(不包含音频)
ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280720 -i “视频源” -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 10M -bufsize 10M -an -f flv “推流地址”

#推流视频
ffmpeg -re -i “视频源” -vcodec copy -acodec aac -b:a 192k -f flv “推流地址”

树莓派摄像头推流示例:

ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280720 -i “/dev/video0” -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 10M -bufsize 10M -an -f flv “rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_43116538_85852610&key=829133b26b0e1111898aac62df55dcf3&schedul=rtmp”

其中/dev/video0 是树莓派摄像头设备节点,作为推流的输入源,flv 后面那串是B站直播间的rtmp地址加上直播码。
树莓派视频推流示例

ffmpeg -re -i “/home/pi/Desktop/python代码/MP4/video.mp4” -vcodec copy -acodec aac -b:a 192k -flvflags no_duration_filesize -f flv “rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_43116538_85852610&key=829133b26b0e1111898aac62df55dcf3&schedul=rtmp”

以下是Windows系统中推流命令

#推流USB摄像头(包含音频,音频源为音频文件)
ffmpeg -f dshow -s 1280720 -r 1024 -i video=“视频源” -stream_loop -1 -i “音频源” -vcodec libx264 -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 5000k -acodec aac -ac 2 -ar 44100 -ab 128k -preset:v ultrafast -tune:v zerolatency -f flv “推流地址”

#推流USB摄像头(包含音频,音频源麦克风)
ffmpeg -f dshow -s 1280720 -r 1024 -i video=“视频源” -i “音频源” -vcodec libx264 -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 5000k -acodec aac -ac 2 -ar 44100 -ab 128k -preset:v ultrafast -tune:v zerolatency -f flv “推流地址”

#推流USB摄像头(不包含音频)
ffmpeg -f dshow -s 1280720 -r 1024 -i video=“视频源” -vcodec libx264 -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 5000k -an -preset:v ultrafast -tune:v zerolatency -f flv “推流地址”

#推流视频
ffmpeg -re -i “视频源” -vcodec copy -acodec aac -b:a 192k -f flv “推流地址”

以上命令没有经过仔细测试,不同环境需要不同的参数,请自行学习FFmpeg的用法。

FFmpeg基本用法:

ffmpeg [全局选项] {[输入文件选项] -i 输入文件} … {[输出文件选项] 输出文件} …

参数简单介绍:

-f:输入格式(video4linux2 )
-i:输入源
-s:视频分辨率
-r:所需的帧率
-vcodec:视频编解码器
-vb:视频比特率
-bufsize:缓冲区大小(对于流来说很重要)
-vf:像素格式
-g:GOP(图片组,对于流式传输很重要)
-an:不使用音频
-f:输出格式

ffpmeg文档

用python实现控制树莓派推流

上面的推流命令是在树莓派终端执行的,那么如何通过运行python程序来进行摄像头推流呢?
我们可以通过python程序调用sh脚本来执行推流命令。python调用shell脚本的方法有很多种,大家可以自己在网上查,我主要尝试了两种:
一、os.system(“command”)方法
这种方法执行成功会返回一个0。
二、os.popen(“command”)方法
这种方法的返回值是一个文件对象,可以通过read()方法获取返回值。例如:

f=popen("sh ./ffmpeg.sh")
print(f.read())

首先,我们新建一个文件,保存为ffmpeg.sh,然后编辑如下内容,保存:

chmod 777 ./ffmpeg.sh   #使脚本具有执行权限
ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280*720 -i "/dev/video0" -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280*720 -g 60 -b:v 10M -bufsize 10M -an -f flv "rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_43116538_85852610&key=829133b26b0e1111898aac62df55dcf3&schedul=rtmp"

python调用shell脚本执行推流代码如下:

import os
os.popen("sh /home/pi/Desktop/python代码/ffmpeg/ffmpeg.sh")

如何停止树莓派推流

在尝试用python调用shell脚本进行摄像头推流时,发现了一个问题,就是不知道怎么停止摄像头推流。
摄像头推流不像视频推流,视频推流在把视频推流完后就结束了,但是摄像头推流会一直进行下去,甚至把python代码停止关闭后脚本依然在后台运行,另外,把B站直播间关闭后推流命令仍然在运行,把python程序和B站直播间关闭后,再次打开B站直播间还是能够看到摄像头画面。除非重启树莓派,否则推流指令就会一直在执行。
因为我想要的效果是开始推流和结束推流都能通过代码来实现,所以就在网上找如何通过一个指令或者代码停止推流,但是找了很久都没有找到具体的方法(如果你们找到了或者有更简单的方法,还请不吝赐教)。以下是我解决问题的过程:
一、首先我在网上查找资料学习如何终止一个脚本,知道可以通过获取其进程的pid,然后用kill -9 pid的方法杀死进程。于是我就想办法和获取sh脚本pid。方法如下:
首先在sh脚本中通过$$获取脚本本身的pid,然后返回给python代码,供python获取,python获取脚本pid后,调用kill函数杀死对应进程。
shell脚本:

chmod 777 ./ffmpeg.sh   #使脚本具有执行权限
echo $$
ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280*720 -i "/dev/video0" -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280*720 -g 60 -b:v 10M -bufsize 10M -an -f flv "rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_431165318_85852610&key=829133b26b0e1111898aac62df55dcf3&schedule=rtmp"

python代码:

import os
import signal
import time
p=os.popen("sh /home/pi/Desktop/python代码/ffmpeg/ffmpeg.sh")
pid=int(p.read()) #返回的pid是字符串,要进行强制类型转换
time.sleep(20)
os.kill(pid,signal.SIGKILL) #第二个参数表示强制杀死进程

但是运行代码之后还是停止不了推流,经检查后发现如果推流成功,存程序会卡在第四行,即调用sh脚本那一行代码。我试过在那一行代码后面进行一个输出,但是运行程序后并没有对应输出,就相当于程序阻塞在了那里,不断进行推流指令,后面的任何程序都无法执行。所以又进行了另一种方法。
二、把推流命令放在一个子进程或子线程中执行,在主进程或主线程中进行kill命令,我选择的是在子线程中执行。
首先修改sh脚本,因为执行推流指令后无法执行后面代码,所以不能直接通过返回值获取pid,要把脚本pid保存在一个文件(/home/pi/Desktop/python代码/ffmpeg/ffmpeg.pid)中,然后主函数就从文件中获取pid。
sh脚本:

chmod 777 ./ffmpeg.sh   #使脚本具有执行权限
echo $$ > /home/pi/Desktop/python代码/ffmpeg/ffmpeg.pid
ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280*720 -i "/dev/video0" -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280*720 -g 60 -b:v 10M -bufsize 10M -an -f flv "rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_431165318_85852610&key=829133b26b0e1111898aac62df55dcf3&schedule=rtmp"

python代码:

import os
import sys
import time
import signal
import threading
pid=-3def doffmpeg():os.popen("sh /home/pi/Desktop/python代码/ffmpeg/ffmpeg.sh")if __name__=='__main__':thread=threading.Thread(target=doffmpeg)thread.start() #开启一个新线程,和开启进程差不多#process=Process(target=doffmpeg)#process.start()time.sleep(20)f=open('/home/pi/Desktop/python代码/ffmpeg/ffmpeg.pid') #从文件中读取pidpid=int(f.read()) #因为读取出来的是字符串,所以要进行强制类型转换print("child_pid=", pid)os.kill(pid,signal.SIGKILL) #第二个参数表示强制杀死进程main_pid=os.getpid()  #python程序pidprint("main_pid=", main_pid)

但是,运行程序并且执行了kill指令后,仍然是无法停止摄像头推流,经和同学讨论后,觉得是pid不正确,推流指令可能是又开设了一个新的进程或线程来执行的。于是,我就在终端用ps -efps -aux指令(ef或aux表示查看全部进程)查看全部进程,发现还真是这样:

由图中可以看出,我们获得的pid和脚本的pid是相同的,但是和推流指令的pid却不一样,并且推流指令的ppid是脚本的pid,说明脚本在执行推流指令时确实是新开了一个进程或者线程。那么如何获得推流指令的pid呢?
三、之后我学习了一些终端指令,发现可以通过进程名称来获取进程pid。
命令 ps
用标准语法查看系统上的每一个进程

ps -e
ps -ef
ps -eF
ps -ely

使用BSD语法查看系统上的每个进程

ps ax
ps axu

-a:显示所有进程(包括其他用户的进程)
-u:用户以及其他详细信息
-x:显示没有控制终端的进程

ps 命令参数介绍

-e: Select all processes. Identical to -A.
-a:显示所有进程(包括其他用户的进程)
-u:用户以及其他详细信息
-x:显示没有控制终端的进程

如何按名称或PID查找一个进程

#名称
ps -ef|grep tomcat
#PID
ps -ef|grep 17850

最简单的方法是使用 pgrep:

pgrep -f name

如果需要查找到 pid 之后 kill 掉该进程,还可以使用 pkill:

pkill -f name

经和同学讨论,我们觉得通过进程名称获取pid是匹配进程名称的关键字的,如下图:

因为我试着直接用推流指令当作名称匹配时出错了,所以我们只好在以下推流指令中找出独一无二、在其他进程或指令中没有的字符串,应该就能准确匹配到我们想要的指令的pid

ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280720 -i “/dev/video0” -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280720 -g 60 -b:v 10M -bufsize 10M -an -f flv “rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_431165318_85852610&key=829133b26b0e1111898aac62df55dcf3&schedule=rtmp”

这里我选取的字符串是/dev/video0,如下图:

发现成功获取推流指令pid。因此,我们可以直接用指令:

pkill -f /dev/video0

通过匹配进程名称的方法kill掉推流进程,而无需再获取pid了。
把上述指令写进另一个shell脚本,想要kill掉推流指令就调用此脚本即可。
shell脚本:

chmod 777 ./stopffmpeg.sh
pkill -f /dev/video0
echo "stop ffmpeg"

python代码:

import os
import sys
import time
import signal
import threading
from multiprocessing import Processdef doffmpeg(pid):os.popen("sh /home/pi/Desktop/python代码/ffmpeg/ffmpeg.sh")if __name__=='__main__':thread=threading.Thread(target=doffmpeg,args=(pid,))thread.start()time.sleep(20)os.popen("sh /home/pi/Desktop/python代码/ffmpeg/stopffmpeg.sh")

最后实现的功能勉强达到了,我感觉我的方法不太正规,但也找不到更好地方法了,如果有谁又更好的方法,欢迎留言,谢谢!

使用树莓派基于FFmpeg推流视频和摄像头到B站直播间相关推荐

  1. 基于ffmpeg+SDL 实时播放摄像头视频

    基于ffmpeg+SDL 实时播放摄像头视频 基本流程 udp接收rtp数据流接收一帧数据后,转换为NAL单元送去解码 (这里特别说明一下,我本次用的接口是支持从连续数据流中自动分割出一个个NAL的, ...

  2. 嵌入式Linux下基于FFmpeg的视频硬件编解码

    嵌入式Linux下基于FFmpeg的视频硬件编解码[图] http://www.c114.net ( 2012/3/1 15:41 ) 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究. ...

  3. 基于 FFMPEG 的视频编码 源码(libavcodec,C++ Qt)

    基于 FFMPEG 的视频编码 源码(libavcodec,C++ Qt) 昨晚把源代码好好整理了一下,加入了视频时间限制功能.源码放这里,大家随便用. 关于代码的解释可以看我另一篇博客: 基于 FF ...

  4. 基于 FFMPEG 的视频编码(libavcodec ,致敬雷霄骅)

    基于 FFMPEG 的视频编码(libavcodec ,致敬雷霄骅) 本文参考了雷博士的博客: 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265)) 还参考了另一篇博客: ...

  5. Qt基于FFmpeg实现视频转码

    一.简述转码 转码的作用:封装格式的实现.(h264->mov.mp4.flv.avi(封装格式)等) 之前博客中提到如何把像素数据编码得到 H264 的压缩码流数据,但是一般的播放工具是没法直 ...

  6. 基于ffmpeg的视频处理与MPEG的压缩试验(下载安装使用全流程)

    基于ffmpeg的视频处理与MPEG的压缩试验 ffmpeg介绍与基础知识 对提取到的图像进行处理 RGB并转化为YUV 对YUV进行DCT变换 对每个8*8的图像块进行进行量化操作 ffmpeg介绍 ...

  7. 不用obs不用直播姬,直接ffmpeg命令行推流RTSP到B站直播间

    最近在做公司的直播准备工作,在尝试过程中,发现公司的"海康威视 DS-2CD1021FD-IW1"摄像头输出的是RTSP格式的. 经过各种搜索,尝试了用B站官方直播姬抓VLC窗口, ...

  8. 用ffmpeg在Windows11下的命令行模式推流到B站直播间

    0. 通过修改环境变量,实现ffmpeg命令在任意命令行路径可用的方法.不用再使用下面的第1步了!! 注意:一路"确定 " 保存设置后,最好重启一下,这样就可以将ffmpeg变成系 ...

  9. 互联网晚报 | 1月25日 星期二 | 知乎首次举办上星晚会;微信视频号上线首个付费直播间;淘宝天猫“春节不打烊”活动正式上线...

    今日看点 ✦ 淘宝天猫"春节不打烊"活动正式上线,20万商家春节照常发货 ✦ 微信视频号上线首个付费直播间,免费观看3分钟后需付费 ✦ 知乎首次举办上星晚会,2022知乎答案奇遇夜 ...

最新文章

  1. centos6.5 rsync+inotify同步配置笔记
  2. worpress安装mysql连不上_wordpress安装时连接不上MySQL8.0(已解决)Windows
  3. 九十五、轻松搞定Python中的Excel办公自动化系列
  4. php 数据库 加载图片,图片显示不出来,但是数据库里有显示
  5. Linux!为何他一人就写出这么强的系统?
  6. 使用mintty(_如何使用Mintty改善Cygwin控制台
  7. 2135亿!2018 双11阿里数据库技术战报新鲜出炉
  8. java中的 =运算符_(二十七)、java中的运算符
  9. Java 使用SAX解析XML文档
  10. java静态常量存在哪里,Java面试题及解析
  11. 热启动计算机的快捷键,电脑快捷键的用法
  12. 分享一个原始传奇的辅助脚本
  13. 清除Tomcat日志
  14. 查询硬盘序列号(serialNumber),系统安装日期等
  15. 数据告诉你,谁是2019年最硬核公链?
  16. 一座5g基站造价多少?
  17. services.msc 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动
  18. 农村信用社计算机基础知识,农村信用社计算机基础知识题五
  19. 喜马拉雅全站音频爬取
  20. 曾经连过的WiFi密码查询

热门文章

  1. Linux下RocketMq可视化工具安装
  2. 2018寒假训练第一场——吃鸡跑毒篇
  3. 虚拟机上安装macOS big sur
  4. 如何将div中的内容垂直居中
  5. 23 OpenCV直方图计算calcHist
  6. C语言——求1到10的阶乘之和
  7. php修改网页中内容,php如何实现html内容替换
  8. 锁住你的记录:sqlserver锁定数据库中的一行记录
  9. 2000管理员密码丢失的找回方法
  10. 宝妈,大学生怎么在家赚钱