デジタル ヒューマン生成にインターフェイスを追加し、ER-NeRF/RAD-NeRF/AD-NeRF、Gradio フレームワークに基づいて WEBUI を構築し、HLS ストリーミング メディアを使用して推論と再生を実現します - パート 3: WEBUI で m3u8 ビデオを再生し、再生中にプッシュします節約

序文

  • 前の 2 つの記事では、Gradio 出力ログと ER-NeRF 推論グラフが ts ファイルに転送されることについて説明しました。
  • この記事では、サーバーによって生成された m3u8 ファイルを Gradio でリアルタイムに再生する方法について説明します。
  • Web 上で再生するには、まずプレーヤー、video.js や hls.js などの hls プロトコルをサポートする Web プレーヤーが必要です。ネイティブ ビデオも再生できます。ここでは hls.js を選択します。 。
  • プレーヤーに加えて、m3u8 ファイルは Web フロントエンドで見つかる必要があります。これは、gradio が URL を介した m3u8 ファイルの直接ロードをサポートできることを意味します。これには、gradio の静的ファイルのマウントが含まれます。
  • また、設計した WebUI にプレーヤーを表示するには、グラデーションを有効にする必要があります。ただし、グラデーションのコンポーネント ライブラリには、hls.js スクリプトをロードできるプレーヤー コンポーネントがありません。ここでコンポーネントをカスタマイズする必要があります。

効果

  • プレーヤーがロードされていないときのインターフェース:
    ここに画像の説明を挿入します
  • プレーヤーをロードした後のコンポーネント:
    ここに画像の説明を挿入します

成し遂げる

まず、gradio が URL 経由で m3u8 静的ファイルをロードできるようにする必要があります。
この目標を達成するには、FastAPI を導入し、FastAPI を使用して静的ディレクトリをマウントし、その後 gradio で FastAPI をマウントする必要があります。

#设置静态目录
app = FastAPI()
dir = os.path.abspath(os.getcwd()) #将当前根目录作为静态目录
app.mount('/static', StaticFiles(directory=dir), 'static')

gradio と FastAPI を一緒にマウントします (現在、gradio 自体がキューをサポートする必要があります)。https://www.gradio.app/docs/mount_gradio_app を参照してください。

#将fastapi的静态目录和gradio挂载一起
page = page.queue()
app = gr.mount_gradio_app(app, page,path='/')

これを実行すると、gradio の .launch() メソッドを使用してアプリケーションを起動できなくなります。
launch() が開始された後は FastAPI 効果はなく、マウントは開始されます。無駄

ここからは Uvicorn を使用します。Uvicorn についてはオンライン情報を参照してください。

uvicorn main-webui:app --port 7861 #端口好不指定默认为8000

起動後、http://127.0.0.1/static/xx/xx/xx.m3u8 を通じてビデオ インデックス ファイルにアクセスできます。

次に、Gradio のビデオ コンポーネントをカスタマイズし、ビデオを再生させます。
ビデオの m3u8 ファイルの URL は動的に生成されるため、クライアントはサーバーのログ メッセージを聞くことしかできません。特別なメッセージが表示されると、クライアントは m3u8 アドレスが表示されたと認識します。メッセージを解析し、ビデオ インデックス ファイルの URL を取得して、再生用のビデオ コンポーネントを構築するだけです。
したがって、まず前の log_out 関数を変換し、特定のメッセージ内の m3u8 アドレスを解析させます。次に、ビデオ HTML コード文字列を Web に出力します。フロントエンド ログ解析コードがこの HTML コードを読み取った後、インターフェイス上の特定の場所にこのコードをレンダリングします。

video_div = '<div id="videoDiv" style="width:100%;height:512px;"><video style="width:100%;height:100%;" id="videoDom" controls m3u8="[M3U8URL]"></video></div>'
def log_out(new_log):
    print(new_log)
    if new_log.find('##M3U8##SUCCESS:')>-1:
        #根据日志输出的信息处理,提取到m3u8的地址
        video = new_log.replace('##M3U8##SUCCESS:', '')
        video = video_div.replace('[M3U8URL]', video)
        time.sleep(0.7) #让客户端有时间来出来视频显示
        print('输出video:'+video)
        return video
    return new_log

次に、webui でログ出力関数のコードを変換します。
元のコードを参照してください: ER-NeRF/RAD-NeRF/AD-NeRF に基づいたデジタル ヒューマン生成へのインターフェイスの追加, Gradio フレームワークは WEBUI を構築し、HLS ストリーミング メディアを使用して推論と再生を実現します - 1: WEBUI でのサーバー コンソール ログのリアルタイム出力: https://blog.csdn.net/AJian759447583/article/details/133990434

_script = '''
   async()=>{
      .......
      //将hls.js的代码加入到页面上
      ......
       //监控日志输出及显示
       			let video= document.querySelector("#videoDivCom");
               let output = document.querySelector("#logDivText .border-none");
               if(!output){
                   return false;
               }
               let show = document.querySelector('#logShowDiv .container')
               show.style.height='200px'
               show.style.overflowY='scroll'
               show.innerHTML=""
               Object.defineProperty(output, "value", {
                   set:  function (log) {
                       if(log && log!=''){
                           	if(log.startsWith('<div id="videoDiv"')){
                                     video.innerHTML=log                  
                                }else{
                                    show.innerHTML = show.innerHTML+'<br>'+log
                                    show.scrollTop=show.scrollHeight
                                }
                       }      
                       return this.textContent = log;
                   }
               });
               ......
   }
'''
#在page页面加载的时候,将自定义的js加载进去
page.load(_js=_script)

このようにして、ビデオをページに動的にロードすることができ、サーバー GPU がビデオの転送中に CPU を推論し、同時に Webui クライアントがビデオを再生するという効果が得られます。

次に、このプロセスの各時点を高速化し、より優れたより高速なサーバーを使用し、リアルタイム TTS を統合すると、テキストに基づいて指定された音声をリアルタイムで生成し、指定された音声を自動的に推測するデジタル ヒューマン ビデオが作成されます。準備ができている!

もちろん、対処する必要のある詳細は 1 億件あるはずです...
上記の 3 つの記事を含め、これらは全体的な考え方の一般的な説明にすぎません。 、具体的な実装は間違いなく、対処する必要がある詳細がまだ 1 億件あります。前の 2 つの記事:

要約する

  • 全体的なアイデアは非常にシンプルかつ簡単で、技術的なギャップはありません。
  • 細かい点で検討すべきことが多すぎて、各ステップで細かい技術的な部分に行き詰まり、さまざまな検討や試みが行われ、最終的には N 時間以上かけて解決する必要があるテスト中 - もちろんありますが、まだ解決できない可能性があります
  • 今回使用されている馴染みのないテクノロジは、これまでに公開されたことがないか、馴染みのないテクノロジです。
    1: サーバー ログはリアルタイムで Web クライアントに出力されます (一定の時間を費やします)。実験に多くの時間を要します)
    2: Python のグラデーション フレームワーク (公式 Web サイトから学ぶことができ、簡単に始めることができます)
    3: ffmpeg コマンド (非常に複雑です、私の頭では痛い...)
    4: Python で ffmpeg のパイプラインを使用する (理解するのは簡単ですが、入力パイプラインが同時にパイプラインでもある場合、調査と試行に多くの時間を費やしました) 、しかし結局解決策はありませんでした)
    5:Gradioのキュー、fastapi、静的ファイル(しばらく解決策を探して数時間試しました)
    6: HLS ストリーミング プロトコル (スキミング)
    7: m3u8 ファイル形式 (注意事項)
    8: ts 形式メディア ファイルのパケット プロトコルの詳細 (ffmpeg の場合)は ts に変換されます。VLC プレーヤーには通常のオーディオとビデオがありますが、hls.js は Web) 画面でサウンドのみを再生します。この問題の解決に多くの時間を費やし、さまざまなパラメーターを試した結果、最終的に有効なパラメーターは次のとおりであると判断しました。 vcodec='libx264', r=25,output_ts_offset=ts_index * 5,hls_time=5,hls_segment_type='mpegts')
  • さらに最適化してほしい点: パイプライン入力とパイプライン出力には Python の ffmpeg を使用します。現在、パイプの入出力を同時に行うとプログラムがハングアップし、1フレームのデータを書き込み、1フレームのデータを読み出しても同様の現象が発生し、現在解決されていません。

おすすめ

転載: blog.csdn.net/AJian759447583/article/details/133995773