Packages
bpe
0.7.16
13.5.22-aleph
11.4.16
11.4.15
11.4.14
11.4.13
9.9.7
9.9.6
8.12.4
8.12.3
8.12.1
8.12.0
retired
8.2.1
8.2.0
8.1.0
7.11.0
7.10.4
7.10.3
7.10.2
7.10.1
7.9.1
7.9.0
7.8.2
7.8.1
7.8.0
7.6.4
7.6.3
7.6.2
7.6.1
7.6.0
7.5.15
7.5.14
7.5.13
7.5.12
7.5.11
7.5.10
7.5.9
7.5.8
7.5.7
7.5.6
7.5.5
7.5.3
7.5.2
7.5.1
7.5.0
7.4.11
7.4.10
7.4.9
7.4.8
7.4.7
7.4.6
7.4.5
7.4.4
7.4.3
7.4.2
7.4.1
7.4.0
7.3.0
7.2.8
7.2.7
7.2.6
7.1.6
7.1.5
7.1.4
7.1.3
7.1.2
6.12.7
6.12.6
6.12.5
6.12.3
6.12.2
6.12.1
6.12.0
6.11.0
6.10.0
6.5.3
6.5.2
6.5.1
6.5.0
6.4.0
6.3.0
5.12.0
5.11.4
5.11.3
5.11.2
5.11.1
5.11.0
5.8.7
5.8.6
5.8.5
5.8.4
5.8.3
5.8.2
5.8.1
5.8.0
5.7.0
5.6.0
5.5.2
5.5.1
5.4.0
5.2.0
5.1.3
5.1.2
5.1.1
4.12.4
4.12.3
4.12.2
4.12.1
4.12.0
4.11.8
4.11.7
4.11.6
4.11.5
4.11.4
4.11.3
4.11.2
4.11.1
4.11.0
4.10.24
4.10.23
4.10.22
4.10.21
4.10.20
4.10.19
4.10.18
4.10.17
4.10.16
4.10.15
4.10.14
4.10.13
4.10.12
4.10.11
4.10.10
4.10.9
4.10.8
4.10.7
4.10.6
4.10.5
4.10.4
4.10.3
4.10.2
4.10.1
4.10.0
4.9.18
4.9.17
4.9.16
4.9.15
4.9.14
4.9.13
4.9.12
4.9.11
4.9.10
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.1
4.8.0
4.7.5
4.7.3
4.7.2
4.7.1
4.7.0
4.6.0
2.4.0
0.7.16
ERP/1: RTP GST WebRTC ICE SDP H.264 H.265 MP4 MPEG-2 HLS HEVC
Current section
Files
Jump to
Current section
Files
lib/rtp/live_stream.ex
defmodule Rtp.LiveStream do
import Plug.Conn
def init(options), do: options
def call(conn, _opts) do
case conn.path_info do
["rooms", room_name, "recording.mp4"] ->
file_path = "priv/static/rooms/#{room_name}/recording.mp4"
if File.exists?(file_path) do
conn = conn
|> put_resp_header("content-type", "video/mp4")
|> put_resp_header("cache-control", "no-cache")
|> send_chunked(200)
stream_growing_file(conn, file_path, 0)
|> halt()
else
conn |> send_resp(404, "Not Found") |> halt()
end
["rooms", room_name, file_name] ->
file_path = "priv/static/rooms/#{room_name}/#{file_name}"
cond do
file_name == "index.m3u8" ->
if File.exists?(file_path) do
conn
|> put_resp_header("content-type", "application/vnd.apple.mpegurl")
|> put_resp_header("cache-control", "no-store, no-cache, must-revalidate, max-age=0")
|> send_resp(200, File.read!(file_path))
|> halt()
else
conn
|> put_resp_header("cache-control", "no-store, no-cache, must-revalidate, max-age=0")
|> send_resp(404, "Not Found")
|> halt()
end
String.ends_with?(file_name, ".ts") ->
if File.exists?(file_path) do
{time_us, conn} = :timer.tc(fn ->
conn
|> put_resp_header("content-type", "video/mp2t")
|> put_resp_header("cache-control", "no-store, no-cache, must-revalidate, max-age=0")
|> send_file(200, file_path)
end)
require Logger
Logger.info("Served #{file_name} in #{time_us / 1000} ms")
conn |> halt()
else
conn |> send_resp(404, "Not Found") |> halt()
end
true ->
conn
end
_ ->
conn
end
end
defp stream_growing_file(conn, file_path, offset) do
case File.open(file_path, [:read, :binary]) do
{:ok, file} ->
:file.position(file, {:bof, offset})
case IO.binread(file, 65536) do
:eof ->
File.close(file)
stream_growing_file(conn, file_path, offset)
data when is_binary(data) ->
File.close(file)
case chunk(conn, data) do
{:ok, conn} ->
stream_growing_file(conn, file_path, offset + byte_size(data))
{:error, :closed} ->
conn
end
end
{:error, _} ->
stream_growing_file(conn, file_path, offset)
end
end
end