Rails: アプリケーション コントローラー内のソケット ハイジャック
概要
Rails アプリケーションを使用して生のビデオ ストリームを提供したいと考えています。これを行うための最良の方法は、ソケットをハイジャックしてビデオ ストリーム (遠隔地から送信される) を直接送信することであると理解しました。 つまり、基本的にはビデオリバースプロキシです。 また、これをアプリケーション内でロジックを適用できるようにしたいと考えています。それ以外の場合は、nginxを使用するだけです。 プーマを使っています。
config.ru経由でこれを行うことができましたが、より多くのロジックを使用してリモートへの呼び出しをより動的にできるようにするために、アプリケーションコントローラー内に置きたいと考えています。
私のconfig.ru:
map '/video' do
io_lambda = lambda do |io|
uri = URI("http://10.0.0.20/myvideo.ts")
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri
http.request request do |response|
response.read_body do |chunk|
io.write chunk
end
end
end
end
app = lambda do |env|
response_headers = {}
response_headers['Transfer-Encoding'] = 'binary'
response_headers["Content-Type"] = "video/mp2t"
response_headers["rack.hijack"] = io_lambda
[200, response_headers, nil]
end
run app
end
アプリケーションコントローラーのメソッドに同じものを入れても機能せず、空の応答が返されます。 TemplateError を回避するために :head ok を追加し、 run app 行と app 変数の割り当てを削除しました。 私は Rails にまったく慣れていないので、間違った方法で取り組んでいる可能性があります。私が見つけることができるほとんどのリソースは WebSocket のみに関するものであるため、正しい方向を示す助けをいただければ幸いです。
また、この投稿も知っています。「Rack 用の軽量ストリーミング HTTP プロキシ (Ruby CPU-light HTTP クライアント ライブラリ)」は、私に良い方向を示し、吸収して学ぶべき多くの情報でした。 sendfile gem は最終的な解決策のように思えますが、ソケットをハイジャックしてアプリケーションコントローラーが生データをクライアントにストリーミングするだけの方法がわかりません。
class SocketController < ApplicationController
include ActionController::Live
def test
i = 0
response.headers['Content-Type'] = 'video/mp4'
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri
http.request request do |remote_response|
remote_response.read_body do |chunk|
i += 1
puts i if i % 1000 == 0
response.stream.write chunk
end
end
end
ensure
response.stream.close
end
end
解決策
あなたが直面している問題は、Rails アプリケーション コントローラーのアクションでrack.hijack ヘッダーを使用しようとしているということです。ただし、rack.hijack ヘッダーは config.ru ファイルでのみサポートされます。
Rails アプリケーションで生のビデオ ストリームを提供するには、sendfile gem を使用できます。 sendfile gem を使用すると、最初にファイルをメモリに読み込むことなく、ファイルをクライアントに直接送信できます。これは、ビデオ ストリームなどの大きなファイルを提供するのに最適です。
sendfile gem を使用するには、それを Gemfile に追加する必要があります。
gem 'sendfile'
次に、Rails アプリケーション コントローラーの send_file メソッドを使用して、ビデオ ストリームをクライアントに送信できます。
def stream_video
send_file '/path/to/video.mp4', type: 'video/mp4'
end
send_file メソッドは、送信するファイルへのパスとファイルのコンテンツ タイプという 2 つの引数を取ります。この場合、ファイルは /path/to/video.mp4 にあり、コンテンツ タイプは video/mp4 です。
sendfile gem を使用して、リモートの場所から生のビデオ ストリームを提供することもできます。これを行うには、まず Net::HTTP ライブラリを使用してビデオ ストリームを Rails アプリケーションにダウンロードする必要があります。次に、send_file メソッドを使用してビデオ ストリームをクライアントに送信できます。
以下は、リモートの場所から生のビデオ ストリームを提供する方法の例です。
def stream_video
uri = URI('http://example.com/video.mp4')
response = Net::HTTP.get(uri)
send_file response.body, type: 'video/mp4'
end
このコードは、まずビデオ ストリームをリモートの場所から応答と呼ばれる変数にダウンロードします。次に、send_file メソッドを使用してビデオ ストリームをクライアントに送信します。
お役に立てれば幸いです!