defmodule Exstream do
def get_closest_packet_to_byte(packets, byte) do
Enum.min_by(packets, fn x -> abs(String.to_integer(x["pos"]) - byte) end)
end
def get_packets(%{"packets" => packets}) do
packets
end
def get_keyframe_packets(%{"packets" => packets}) do
packets
|> Enum.filter(fn x -> x["flags"] === "K_" end)
end
def get_duration(%{"format" => %{"duration" => duration}}) do
{integer, _remainder_of_binary} = Integer.parse(duration)
integer
end
def get_result({result, 0}) do
result
end
def get_one_tenth(n) do
floor(n / 10)
end
def get_steps(n) do
Enum.to_list(0..floor(n) // get_one_tenth(n))
end
def get_step(duration, step) do
Enum.at(get_steps(duration), step)
end
def get_next_step_index(steps, step) do
Enum.find_index(steps, fn x -> x > step end)
end
def probe(file) do
System.cmd("ffprobe", [
"-i", file,
"-show_entries", "format=duration:packet=pos,pts_time,flags",
"-select_streams", "v",
"-of", "json",
"-v", "0"
])
|> get_result()
|> Jason.decode!()
end
def segment(file, step) do
duration = probe(file) |> get_duration()
next_step = Enum.at(get_steps(duration), get_next_step_index(get_steps(duration), step))
{result, _exit_status} = System.cmd("ffmpeg", [
"-hide_banner",
"-loglevel", "error",
"-copyts",
"-ss", "#{ step }",
"-i", file,
"-c", "copy",
"-to", "#{ next_step }",
"-f", "mpegts",
"pipe:"
])
result
end
end