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

2023-05-16

文章目录

    • 从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=-3

def 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') #从文件中读取pid
    pid=int(f.read()) #因为读取出来的是字符串,所以要进行强制类型转换
    print("child_pid=", pid)
	os.kill(pid,signal.SIGKILL) #第二个参数表示强制杀死进程

    main_pid=os.getpid()  #python程序pid
    print("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 Process

def 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")

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 排序算法——插入排序

    目录 x1f3a8 基本介绍 x1f3b9 算法思想 x1f3f8 实例 x1f3a0 思路分析 x1fa81 代码实现 x1f6f9 算法性能分析 x1f680 时间复杂度 x1f6f4 空间复杂度 x1f6f8 稳定性 x1f3a8 基
  • 排序算法——希尔排序

    目录 x1f6f4 基本介绍 算法思想 x1f6f9 实例 思路分析 代码实现 x1f6f5 算法性能分析 x1f6f4 基本介绍 希尔排序也是一种插入排序 xff0c 它是简单插入排序经过改进之后的一个更高效的版本 xff0c 也称为见效
  • 旋转矩阵与欧拉角

    其他相关的内容网上很多 xff0c 这里就简单记录一下不同欧拉角分解顺序时 xff0c 对应的角度怎么计算 include lt opencv2 opencv hpp gt include lt iostream gt using name
  • Java中数组的5种拷贝方法

    目录 1 for循环 示例代码 2 调用clone xff08 xff09 方法 示例代码 3 Arrays类中的Arrays copyOf xff08 xff09 方法 示例代码 4 copyOfRange xff08 xff09 方法
  • MySQL 表中数据的增删改查操作

    文章目录 一 在表中插入数据 xff08 1 xff09 单条数据插入 xff08 2 xff09 插入多条数据 二 删除表中数据 三 修改表中数据 四 查询表中的数据 xff08 单表查询 xff09 1 去重查询 distinct 2
  • MySQL中多表查询、表连接(内连接和外连接)

    文章目录 表与表的关系 一对一关系 一对多关系 多对多关系 表与表之间的连接 笛卡尔积 什么是笛卡尔积 xff1a 内连接 xff1a 1 通过where关键字进行关联 2 通过inner join on进行关联 外连接 xff1a 1 左
  • MySQL中索引与事务内容总结

    文章目录 x1f440 1 一 索引介绍 1 索引的优缺点 二 索引分类 三 索引的创建与删除 1 在创建表时创建索引 2 在已经存在的表上创建索引 第一种 xff1a 通过create语法创建索引 第二种 xff1a 通过alter语法创
  • Linux Ubuntu 命令行文件系统的创建,挂载,卸载

    我在刚开始操作的时候找不到 dev sdb 即使插入了U盘 xff0c 也没出现 经过翻阅网站 xff0c 才知道要创建新的硬盘 xff08 xff09 其余默认就行 文件系统的创建 1 查看新增硬盘的信息 sudo fdisk l 2 文
  • 408-数据结构-栈应用-括号匹配&表达式求值

    括号匹配 代码中的括号通常符合一下特性 xff1a 括号成对存在左右括号通常类型匹配 xff0c 大括号匹配大括号 如果存在括号序列 xff08 xff08 xff08 xff08 xff09 xff09 xff09 xff08 xff09
  • C语言学习笔记——编写求x的n次方的递归函数,在主函数调用并输出

    题目内容 xff1a 编写求x的n次方的递归函数 xff0c 在主函数调用并输出 x为double型 xff0c n为整型 xff0c 函数类型为double型 xff09 输入格式 lf d 输出格式 xff1a f 输入样例 xff1a
  • Python 输出Print( )函数用法

    目录 print 字符串格式化 格式化符号 format格式化函数 f string print objects sep 61 39 39 end 61 39 n 39 file 61 sys stdout flush 61 False o
  • RVIZ中的fixed frame选项以及“For frame [XX]: Fixed Frame [map] does not exist”

    RVIZ 使用的时候如果fixed frame选项设置不正确 xff0c 那么就会无法显示显示相应的数据信息 xff0c 并提示一下错误 xff1a For frame XX Fixed Frame map does not exist t
  • vim/vi 4种替换方法,批量替换,手动替换

    文件内全部替换 xff1a s abc 123 g 注 xff1a 把abc替换成123 如文件内有 xff0c 可用 替换 s abc 123 g 或者 s str1 str2 g 用str2替换文件中所有的str1 xff09 文件内局
  • C++枚举与字符串之间的转换

    template lt typename EnumType gt struct SEnumName static const char List enum ProgLang e cpp e java e csharp const char
  • kubeadm部署k8s集群

    1 准备环境 虚拟机操作系统 Centos7 角色 IP Master 192 168 150 140 Node1 192 168 150 141 Node2 192 168 150 142 2 系统初始化工作 在三台虚拟机上进行如下操作
  • docker部署redis集群+集群扩缩容

    1 集群规划 3主3从 xff1a nameipportredis node 1192 168 150 1106381redis node 2192 168 150 1106382redis node 3192 168 150 110638
  • ceph-deploy部署指定版本ceph集群

    注意 xff1a 16版本的ceph已经不支持ceph deploy xff0c 安装方法见我的博客 xff1a cephadm快速部署指定版本ceph集群 ggrong0213的博客 CSDN博客 1 集群规划 xff1a 主机名IP组件
  • k8s集群部署Java(springboot)项目

    1 java项目打成jar包 1 1 在IDEA开发工具中使用maven工具将开发完成的SpringBoot项目达成jar包 我自己的项目生成的jar为 xff1a demojenkins jar 1 2 将生成jar包上传到装有docke
  • Netty+MongoDB集群+Kafka集群解决高并发以及实现海量数据存储

    1 环境要求 准备一台安装有Docker的虚拟机 2 Netty简单介绍 Netty 是一个高性能 异步的 基于事件驱动的 NIO 框架 Netty简化和流线化了网络应用的编程开发过程 3 MongoDB简单介绍 MongoDB是一个高可用
  • C语言:从键盘随机输入10个整数,然后输出最大值和最小值

    本题有两种解决方法 xff1a 假设法和选择排序法 1 假设法找最值 include lt stdio h gt int main int a 10 i max mini for i 61 0 i lt 10 i 43 43 scanf s

随机推荐

  • MySQL开启ssl证书

    由于在主从复制中数据是明文的 xff0c 所以就大大降低了安全性 因此需要借助ssl加密来增加其复制的安全性 5 6版本之上 主默认含有证书 MySQL 5 7 18 加密连接mysql ssl rsa setup span class t
  • Vmware16安装(详细)

    目录 1 安装VMware 2 创建虚拟机 3 安装centos 3 IP和主机名称配置 1 安装VMware 之前为了学习Linux系统 xff0c 买了阿里云和腾讯云的服务器 xff0c 不奈什么都没干 xff0c 号就被封了 所有想了
  • mybatis-plus 分页插件

    目录 1 前言 2 配置分页插件 2 1 selectPage 测试 2 2 自定义分页功能 1 前言 大家之前肯定都用过PageHelper来进行分页 xff0c 其实mybatisplus中也提供了一个分页插件PaginationInn
  • STM32cubeIDE学习汇总(二)----外部中断控制LED和流水灯

    基于上篇我们已经基本了解了软件界面和如何创建一个项目了 接着我们看如何利用外部按键来控制LED灯的亮灭 xff0c 即外部中断 xff08 本文讲述的是外部中断控制led取反以及如何实现流水灯 xff09 xff08 如果想了解外部中断如何
  • 技术分享 | Frida 实现 Hook 功能的强大能力

    Frida 通过 C 语言将 QuickJS 注入到目标进程中 xff0c 获取完整的内存操作权限 xff0c 达到在程序运行时实时地插入额外代码和数据的目的 官方将调用代码封装为 python 库 xff0c 当然你也可以直接通过其他的语
  • Lora超全知识归纳,对于lora和lorawan的详细介绍

    目录 LORA介绍 LoRa通讯技术 网关信道 网关负载 LoRa模块信道 节点入网 终端LoRa应用方案 设备唤醒 终端LoRa应用实践 网关详情 Lora和loraWAN LoRaWAN 概貌 LoRaWAN体系结构 LoraWAN g
  • 蒙特卡罗MCNP学习汇总(一)-----MCNP简介及编写第一个程序

    目录 简介 xff1a 什么是MC模拟 介绍 应用 运行 编写第一个程序 格式 程序 讲解 现象 简介 xff1a 什么是MC模拟 一种通过随机抽样解决数学问题的一种数值计算方法 MC方法解决的主要数学问题 数值积分问题 随机物理过程 xf
  • 蒙特卡罗MCNP学习汇总(四)--计数基础-探测器

    MCNP输入文件 Title Card Any information the user desires and describing the particular problem Cell Cards A cell is a 3D reg
  • FPGA学习汇总(六)----数码管显示(1)

    目录 概念 单个数码管显示单个数字 操作 代码 现象 分析 四个数码管定时单个显示数字 分析 代码 四个数码管同时显示 分析 代码 现象 四个数码管同时显示定时转换 分析 代码 概念 我们要搞懂数码管首先要明白几个概念 我们先看一个数码管
  • FPGA学习汇总(七)----数码管显示(2)之计数器

    目录 四位同时显示 16进制计数器 单个数码管十进制计数器 四位数码管十进制计数器 代码 分析 四位同时显示 16进制计数器 module KC8 seg dig clock input clock output 7 0 seg outpu
  • FPGA之四位led灯二进制显示

    代码 xff1a module KC419 led clk 模块名和引脚 output 3 0 led led xff08 四个 xff09 input clk 时钟 reg 3 0 led1 led 四个 reg 24 0 counter
  • JWT签名与本地计算的签名不匹配。JWT有效性无法断言,不应被信任

    JWT签名与本地计算的签名不匹配 JWT有效性无法断言 xff0c 不应被信任 错误 xff1a io jsonwebtoken SignatureException JWT signature does not match locally
  • Java判断回文(正序与反序一样)

    用户输入一串字符串 xff0c Java程序实现对该字符串判断 对回文判断主要分为三种 xff1a 1 纯数字 2 纯字母 3 混合型 1 纯数字 将输入的字符串翻转 xff0c 之后分别转换成int形式 xff0c 比较两个整数大小 xf
  • 数据结构——用栈解决回文字符问题

    回文 回文是指正读反读均相同的字符序列 如 abba 和 abdba 均是回文 xff0c 但 good 不是回文 试写一个算法判定给定的字符序列是否为回文 xff08 提示 xff1a 将一半字符入栈 xff09 所需的知识前提 xff1
  • 使用git在gitee(码云)上创建仓库并且上传代码(超详细)

    一 安装git 可以在git的官网上下载git xff0c 网址为 git scm com 点击下载 xff0c 然后选择自己电脑对应系统的版本下载 博主这里下载的是windows版 xff08 下载慢的同学可以尝试复制下载链接之后到迅雷中
  • MAC OS 安装anaconda之后 conda命令无效

    最近换了mac xff0c 之前安装软件一直被windows惯坏了 xff0c 不是很习惯使用terminal安装 导致安装之后出现了一些小bug xff0c 比如输入conda之后出现 xff1a zsh command not foun
  • #ifdef 和#endif的作用:防止头文件循环引用

    iOS的pch文件中常见的代码解释 一般情况下 xff0c 源程序中所有的行都参加编译 但是有时希望对其中一部分内容只在满足一定条件才进行编译 xff0c 也就是对一部分内容指定编译的条件 xff0c 这就是 条件编译 有时 xff0c 希
  • SQL语句单表查询

    xff1a 代表注释一行 SELECT xff1a 查询关键字 xff0c 遇到select就是做查询 xff1a 代表我们要查询的列 xff0c 位置代表所有列 xff0c 我们也可以相关列 xff0c 当列比较多的时候用逗号分割 FRO
  • 在 Ubuntu 中安装 VSCode

    在 Ubuntu 中安装 VSCode 如果想要通过 ubuntu 安装 vscode 有三种方式 xff0c 可以通过应用中心下载 xff0c 也可以通过安装包下载 xff0c 以及指令安装 方式一 xff1a 首先在 ubuntu 桌面
  • 使用树莓派基于FFmpeg推流视频和摄像头到B站直播间

    文章目录 从B站直播间获取rtmp地址和直播码在终端使用ffpmeg进行视频或摄像头推流用python实现控制树莓派推流如何停止树莓派推流 前提条件 1 首先要有一个树莓派 xff0c 并连接了摄像头 xff0c 且能够访问网络 2 在Bi