Raspberry Piを使用して、ストリーミングビデオとカメラをFFmpegに基づいてステーションBのライブルームにプッシュします


前提条件
1.まず、Raspberry Piがカメラに接続されていて、インターネットにアクセスできる必要があります。
2. Bilibiliで実名認証に合格し、生放送室を開設しました。(非常に簡単です。実名認証に合格すると、直接アクティブ化できます)。
3.FFmpeg。プッシュストリーミングはデフォルトでFFmpegを使用し、FFmpegは公式のRaspberryPiシステムにデフォルトでインストールされます。ffpmeg-versionを使用して詳細情報を表示できます。

ステーションBのライブ放送室からrtmpアドレスとライブコードを取得します

放送局Bの生放送室に申し込んだ後、パソコンで生放送を開始します。パソコンでrtmpアドレスと生放送コードを取得する必要があります。使用するとrtmpアドレスと生放送コードを取得できません。あなたの携帯電話を生放送するジの生放送。
クリックしてライブブロードキャストを開始すると、rtmpアドレスとライブブロードキャストコード(下の図を参照)が表示され、rtmpアドレスとライブブロードキャストコードが一緒にスプライスされて、後でffpmegプッシュストリームのアドレスになります。
ここに画像の説明を挿入します

ffpmegを使用して、端末にビデオまたはカメラをプッシュします

以下は、Raspbianシステムのストリーミングコマンドです。


#Push Stream USBカメラ(オーディオを含む、オーディオソースはオーディオファイル)ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280 720 -i "ビデオソース" -stream_loop -1 -i "オーディオソース" -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280 720 -g 60 -b:v 10M -bufsize 10M -acodec aac -ac 2 -ar 44100 -ab 128k -fflv「プッシュストリームアドレス」


#プッシュストリームUSBカメラ(オーディオ、オーディオソースマイクを含む)ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280 720 -i "video source" -i "audio source" -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280 720- g 60 -b:v 10M -bufsize 10M -acodec aac -ac 2 -ar 44100 -ab 128k -fflv「プッシュストリームアドレス」


#Push Stream USBカメラ(オーディオを含まない)ffmpeg -thread_queue_size 512 -f video4linux2 -s 1280 720 -i "video source" -vcodec h264_omx -pix_fmt yuv420p -r 30 -s 1280 720 -g 60 -b:v 10M -bufsize 10M -an -fflv「プッシュストリーミングアドレス」


推流视频ffmpeg -re -i "ビデオソース" -vcodec copy -acodec aac -b:a 192k -f flv "プッシュストリームアドレス"

Raspberry Piカメラストリーミングの例:

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”

その中で、/ dev / video0はストリーミングの入力ソースとして使用されるRaspberryPiカメラデバイスノードです。flvの後の文字列は、ステーションBのライブブロードキャストルームのrtmpアドレスとライブブロードキャストコードです。
RaspberryPiビデオストリーミングの例

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 1280 720 -r 1024 -i video = "video source" -stream_loop -1 -i "audio source" -vcodec libx264 -pix_fmt yuv420p -r 30 -s 1280 720 -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 1280 720 -r 1024 -i video = "video source" -i "audio source" -vcodec libx264 -pix_fmt yuv420p -r 30 -s 1280 720 -g 60 -b:v 5000k -acodec aac -ac 2 -ar 44100 -ab 128k -preset:v ultrafast -tune:v zerolatency -f flv "プッシュストリームアドレス"

#Push Stream USBカメラ(オーディオを含まない)
ffmpeg -f dshow -s 1280 720 -r 1024 -i video = "video source" -vcodec libx264 -pix_fmt yuv420p -r 30 -s 1280 720 -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を使用してRaspberryPiプッシュストリーミングを制御する

上記のプッシュストリーミングコマンドはRaspberryPiターミナルで実行されますが、Pythonプログラムを実行してカメラをプッシュするにはどうすればよいですか?
Pythonプログラムを使用して、shスクリプトを呼び出してpushstreamコマンドを実行できます。Pythonがシェルスクリプトを呼び出す方法はたくさんあります。インターネットで確認できます。主に2つ試しました
。1。os.system( "command")メソッド。
このメソッドは、正常に実行されると0を返します。
2. 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は、シェルスクリプトを呼び出して、次のようにプッシュストリーミングコードを実行します。

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

RaspberryPiでストリーミングを停止する方法

Pythonを使用してシェルスクリプトを呼び出してカメラをプッシュしようとすると、問題が見つかりました。つまり、カメラを停止する方法がわかりません。
カメラプッシュはビデオプッシュとは異なります。ビデオプッシュはビデオがプッシュされた後に終了しますが、Pythonコードが停止されて閉じられた後でも、カメラプッシュは続行されます。さらに、スクリプトはバックグラウンドで実行されます。さらに、Bを配置します。ステーションライブ放送室を閉じた後もプッシュストリーミングコマンドは実行されています。PythonプログラムとステーションBのライブ放送室を閉じた後も、ステーションBのライブ放送室を再度開くとカメラ画面が表示されます。Raspberry Piを再起動しない限り、プッシュ命令は常に実行されます。
プッシュの開始と終了の両方がコードで達成できるという効果が欲しいので、インターネット上の命令やコードでプッシュを停止する方法を見つけましたが、長い間特定の方法を見つけられませんでした時間(見つけた場合、またはもっと簡単な方法がある場合は、遠慮なく私に教えてください)。問題を解決する私のプロセスは次のとおりです
。1。まず、インターネットでスクリプトを終了する方法を学ぶための情報を見つけ、そのプロセスのpidを取得できることを知ってから、そのkill -9 pidメソッドを使用しプロセスを強制終了します。そこで、私は方法を見つけて、shスクリプトのpidを取得しようとしました。メソッドは次のとおりです。
まず、shスクリプト$$でスクリプト自体のpidを取得し、それをpythonのpythonコードに戻して取得します。pythonがスクリプトpidを取得したら、kill関数を呼び出して対応するプロセスを強制終了します。
シェルスクリプト:

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) #第二个参数表示强制杀死进程

しかし、コードを実行した後もプッシュを停止することはできません。確認したところ、プッシュが成功した場合、ストアドプログラムは4行目、つまりshを呼び出すコード行でスタックすることがわかりました。脚本。そのコード行の後に出力を実行しようとしましたが、プログラムの実行後に対応する出力がありません。これは、プログラムがそこでブロックされ、命令を継続的にプッシュすることに相当し、後続のプログラムを実行できません。そこで、別の方法を実行しました。
2.サブプロセスまたはサブスレッドで実行するpushコマンドを配置し、メインプロセスまたはメインスレッドでkillコマンドを実行します。サブスレッドで実行することを選択しました。
最初にshスクリプトを変更します。これは、プッシュ命令の実行後に次のコードを実行できないため、戻り値からpidを直接取得できず、スクリプトpidをファイル(/ home / pi / Desktop /)に保存する必要があるためです。 python code / ffmpeg / ffmpeg.pid)次に、main関数はファイルから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 -eforps -auxコマンド(efまたはauxを使用してすべてのプロセスを表示)を使用してすべてのプロセス表示したところ、実際には次のようになっていることがわかりまし
ここに画像の説明を挿入します
た。図からわかるように、取得したpidはスクリプトのpidですが、プッシュストリームと同じです。命令のpidは異なり、プッシュ命令のppidはスクリプトのpidであり、スクリプトが実際に開かれたときに新しいプロセスまたはスレッドが開かれることを示します。プッシュ命令を実行します。では、プッシュ命令のpidを取得する方法は?
3.いくつかのターミナルコマンドを学習した後、プロセスpidはプロセス名で取得できることがわかりました。
コマンドps
は、標準の構文を使用して、システム上のすべてのプロセスを表示します

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

BSD構文を使用して、システム上のすべてのプロセスを表示します

ps ax
ps axu

-a:すべてのプロセス(他のユーザーのプロセスを含む)を表示します
-u:ユーザーおよびその他の詳細情報
-x:端末を制御しないプロセスを表示します

psコマンドパラメータの紹介

-e:すべてのプロセスを選択します。-Aと同じです。-
a:すべてのプロセス(他のユーザーのプロセスを含む)を表示します。-
u:ユーザーおよびその他の詳細情報
-x:端末を制御しないプロセスを表示します。

名前またはPIDでプロセスを見つける方法

#名前
PS -ef | grep Tomcat
#PID
PS -ef | grep 17850

最も簡単な方法はpgrepを使用することです:

pgrep -f name

pidを見つけた後でプロセスを強制終了する必要がある場合は、pkillを使用することもできます。

pkill -f name

クラスメートと話し合った結果、次の図に示すように、プロセス名でpidを取得することは、プロセス名と一致するキーワードであると感じまし
ここに画像の説明を挿入します
た。プッシュ命令を名前の一致として直接使用しようとしたため、エラーが発生しました。次のプッシュ命令を使用する必要がありました。他のプロセスや命令にない一意の文字列を見つけてください。必要な命令の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”

ここで選択した文字列は/dev/video0次の図のようになります。
ここに画像の説明を挿入します
プッシュ命令pidが正常に取得されたことがわかりました。したがって、次のコマンドを直接使用できます。

pkill -f / dev / video0

プロセス名を照合killすることにより、pidを取得する必要なしにプッシュプロセスドロップされます。
上記の命令を別のシェルスクリプトに記述し、プッシュ命令を強制終了する場合はこのスクリプトを呼び出します。
シェルスクリプト:

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

最終的に達成された機能はほとんど達成されていません。私の方法は正式ではないと感じていますが、より良い方法を見つけることができません。誰かがより良い方法を持っているなら、メッセージを残してください、ありがとう!

おすすめ

転載: blog.csdn.net/qq_50866711/article/details/113839586