@Action(方法= [ ' GETは' ]、ディテール= 真) DEFビデオ(セルフ、リクエスト、PK = なし): "" " ライブビデオストリームを取得します :PARAM要求: :のparam PK: :リターン: " "" device_obj = self.get_object() #device_obj.status IF == 0: # 応答を返す({ 'エラー': 'デバイスオフ'}) IF 否定device_obj.rtsp_addressは: 返す応答({ ' エラー':' 欠落RTSPアドレス'}) のcache_id =' _Video_stream_ {} ' .format(device_obj.hash) cache_status = cache.get(のcache_id、なし) IF cache_statusはありませんなし: #タスクの初期化、初期時間設定 cache.set(のcache_id、time.time()を、タイムアウト= 60 ) elifのでisinstance(cache_status、フロート)と:cache_status> 30 - time.time() #のタスクがタイムアウトした、チームへの代わりに、一定期間のエラーメッセージを返す リターン応答({ 「エラー」:" 接続の数が制限を超えて、お待ちくださいもう一度やり直してください" }) RETJob_queue.enqueue_video =(rtsp_address = device_obj.rtsp_address、device_hash = device_obj.hash) logger.info(' ビデオデバイスのジョブステータス%のSをFETCH:%Sを' 、PK、ret._status) のIF ret._status == Bは' 開始' または 「開始」: #のビデオは、リターンビデオIDの通常のプッシュリフレッシュ再生時間にストリーム cache.set(のcache_idは、「続行」、タイムアウト= 30 ) を返すレスポンスを({ 「ビデオ」:「」.join([settings.FFMPEG_VIDEO 、device_obj.hash])}) のelif RET。_status == B「キュー」 または 「キュー」: #のビデオタスク待ちの リターンをレスポンス({ 「ステータス」:「ビデオの接続を確立するために待っている」}) 他には: #ビデオタスクを確立するには、失敗 を返す(レスポンス{ 「エラー」:「オープンビデオに失敗しました」 } )
クラスJobQueue: "" " リアルタイムビデオプレーヤー" "" DEF __init__ (セルフ): self.video_queue = django_rq.get_queue(' ビデオ') #のビデオは、プッシュメッセージキューストリーム DEF :enqueue_video(セルフ、rtsp_address、device_hash) "" " ビデオキューの流れ"" " JOB_ID = ' 動画_ {} ' .format(device_hash) 仕事 = self.video_queue.fetch_job(JOB_ID) IF ない仕事: 仕事 = self.video_queue。enqueue_call( FUNC= ' utils.ffmpeg.ffmpeg_play ' 、 引数 = (rtsp_address、device_hash)、 タイムアウト = -1 、 TTL = 30、 #最多等待30秒 result_ttl = 0、 JOB_ID = JOB_ID ) リターンジョブ
#- * -コーディング:UTF-8 - * - 輸入サブプロセス のインポートスレッド インポート時間 インポートログを から django.core.cache インポートキャッシュ ロガー = logging.getLogger(' server.default ' ) デフffmpeg_play(ストリーム、名): プレイ = 真 のcache_id = ' _video_stream_ {} ' .format(名前) cache.set(のcache_id、' 継続'、タイムアウト= 30 ) 工程 = なし DEF上流(): CMD = " ffmpegの-i '{}' -c:V H264 -f FLV -r 25 -an 'RTMP://127.0.0.1:1935 / LIVE / {}' " .format(ストリーム、名前) プロセス = subprocess.Popen(CMD、シェル= Trueを、STDIN = subprocess.PIPE、標準エラー= subprocess.DEVNULL) トライ: logger.info(' デバイス:{}ストリームスレッド開始:{} ' .format(名前、ストリーム) ) 一方、再生: time.sleep( 1 ) 以外Eとして例外: logger.info(' デバイス:{}ストリームスレッドエラー{} ' .format(名前、E)) 最後に: logger.info(' デバイス:{}ストリームスレッド停止' .format(名)) process.communicate(B ' Q ' ) THR = threading.Thread(目標= 上流) thr.start() してみてください: 一方TRUE: 遊び = cache.get(のcache_id、'' ) であれば!プレイ= ' 続ける' : logger.info(' 停止装置{}ビデオストリーム' .format(名)) プレイ =偽 ブレーク time.sleep( 1 ) 以外Eとして例外: logger.info(' デバイス:{}再生ストリームのエラー{} ' .format(名前、E)) process.communicate(B ' Q ' ) logger.info(' 待機デバイス{}ビデオスレッド停止' .format(名)) thr.join() logger.info(' デバイス{}ビデオジョブ停止」 .format(名))
#リアルタイムストリーミングビデオ RQ_QUEUESを= { ' ビデオ' :{ ' USE_REDIS_CACHE ':' ビデオ' 、 } }