Skip to content

Commit

Permalink
fix: fix keyframes
Browse files Browse the repository at this point in the history
  • Loading branch information
trueChazza committed Feb 9, 2024
1 parent 0df69fe commit 9cd139c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 58 deletions.
24 changes: 14 additions & 10 deletions lib/hls_playlist.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ defmodule HlsPlaylist do
|> Enum.filter(fn x -> String.contains?(x, "K__") end)
end)
|> Enum.reject(fn x -> Enum.empty?(x) end)
|> Enum.map(fn x -> String.trim_leading(Enum.at(x, 0), "packet,") end)
|> Enum.map(fn x ->
String.trim_leading(Enum.at(x, 0), "packet,")
|> String.trim_trailing(",K__")
|> String.split(",")
|> Kernel.hd()
|> String.to_float
end)
end

def get_segments(keyframes, duration, segment_length) do
Expand All @@ -54,12 +60,12 @@ defmodule HlsPlaylist do
end

kf_distance = kf - last_segment
kf_distance_from_desire = abs(desired_segment_length - kf_distance)
kf_distance_from_desire = Kernel.abs(desired_segment_length - kf_distance)

kf_next_distance_from_desire =
case {kf_next, kf_next_distance} do
{nil, _} -> nil
{_next_kf, next_distance} -> abs(desired_segment_length - next_distance)
{_next_kf, next_distance} -> Kernel.abs(desired_segment_length - next_distance)
end

cond do
Expand All @@ -84,26 +90,24 @@ defmodule HlsPlaylist do
end

def get_playlist(segment_lengths, segment_name) do
{playlist_segments, largest_segment} =
{segments, largest_segment} =
Enum.reduce(segment_lengths, {[], 0.0}, fn segl, {acc, current_largest} ->
largest_segment = max(segl, current_largest)

playlist_segment =
extinf_segment =
"#EXTINF:#{String.Chars.to_string(segl)},\n#{segment_name}#{length(acc)}.ts"

{[playlist_segment | acc], largest_segment}
{[extinf_segment | acc], largest_segment}
end)

largest_segment_rounded = trunc(Float.floor(largest_segment))

"""
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:#{largest_segment_rounded}
#EXT-X-TARGETDURATION:#{Kernel.trunc(Float.floor(largest_segment))}
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#{Enum.join(Enum.reverse(playlist_segments), "\n")}
#{Enum.join(Enum.reverse(segments), "\n")}
#EXT-X-ENDLIST\
"""
end
Expand Down
69 changes: 21 additions & 48 deletions test/hls_playlist_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,27 @@ defmodule HlsPlaylistTest do
use ExUnit.Case
doctest HlsPlaylist

@media_path "dev/sample__1080__libx264__ac3__30s__video.mp4"

test "get_duration" do
assert HlsPlaylist.get_duration("dev/sample__1080__libx264__ac3__30s__video.mp4") == 30.0
assert HlsPlaylist.get_duration(@media_path) == 30.0
end

test "get_keyframes" do
assert HlsPlaylist.get_keyframes("dev/sample__1080__libx264__ac3__30s__video.mp4") == [
"0.000000,-0.033333,K__",
"4.166667,4.133333,K__",
"8.333333,8.300000,K__",
"12.500000,12.466667,K__",
"16.266667,16.233333,K__",
"20.133333,20.100000,K__",
"24.300000,24.266667,K__",
"27.433333,27.400000,K__"
assert HlsPlaylist.get_keyframes(@media_path) == [
0.0,
4.166667,
8.333333,
12.5,
16.266667,
20.133333,
24.3,
27.433333
]
end

test "get_segments" do
keyframes = [
0.000000,
4.166667,
8.333333,
12.500000,
16.266667,
20.133333,
24.300000,
27.433333
]

duration = 30.0
segment_length = 3

assert HlsPlaylist.get_segments(keyframes, duration, segment_length) ==
assert HlsPlaylist.get_segments(HlsPlaylist.get_keyframes(@media_path), HlsPlaylist.get_duration(@media_path), 3) ==
[
4.166667,
4.166666,
Expand All @@ -48,28 +36,15 @@ defmodule HlsPlaylistTest do
end

test "get_playlist" do
segment_lengths =
[
4.166667,
4.166666,
4.166667,
3.766667,
3.866666,
4.166667,
3.133333,
2.566667
]
assert HlsPlaylist.get_playlist(HlsPlaylist.get_segments(HlsPlaylist.get_keyframes(@media_path), HlsPlaylist.get_duration(@media_path), 3), "segment") ==

segment_name = "segment"

# a little off from ffmpeg-generated.m3u8
#
# #EXTINF:4.166666, should be #EXTINF:4.166667
# segment1.ts
#
# #EXTINF:3.866666, should be #EXTINF:3.866667
# segment4.ts
expected_playlist =
# a little off from generated-ffmpeg.m3u8
#
# #EXTINF:4.166666, should be #EXTINF:4.166667
# segment1.ts
#
# #EXTINF:3.866666, should be #EXTINF:3.866667
# segment4.ts
"""
#EXTM3U
#EXT-X-VERSION:3
Expand All @@ -95,7 +70,5 @@ defmodule HlsPlaylistTest do
segment7.ts
#EXT-X-ENDLIST\
"""

assert HlsPlaylist.get_playlist(segment_lengths, segment_name) == expected_playlist
end
end

0 comments on commit 9cd139c

Please sign in to comment.