@@ -5,23 +5,61 @@ defmodule Shinkai.Config do
55
66 @ top_level_keys [ :rtmp , :server , :hls ]
77
8- @ default_config [
9- rtmp: [
10- enabled: true ,
11- port: 1935
8+ @ rtmp_schema [
9+ enabled: [
10+ type: :boolean ,
11+ default: true ,
12+ doc: "Enable or disable rtmp"
1213 ] ,
13- server: [
14- enabled: true ,
15- port: 8888 ,
16- certfile: nil ,
17- keyfile: nil
14+ port: [
15+ type: { :in , 0 .. ( 2 ** 16 - 1 ) } ,
16+ default: 1935 ,
17+ doc: "RTMP listening port"
18+ ]
19+ ]
20+
21+ @ server_schema [
22+ enabled: [
23+ type: :boolean ,
24+ default: true ,
25+ doc: "Enable or disable http(s) server"
26+ ] ,
27+ port: [
28+ type: { :in , 0 .. ( 2 ** 16 - 1 ) } ,
29+ default: 8888 ,
30+ doc: "http port"
31+ ] ,
32+ certfile: [
33+ type: :string ,
34+ doc: "https certificate"
35+ ] ,
36+ keyfile: [
37+ type: :string ,
38+ doc: "https private key certificate"
39+ ]
40+ ]
41+
42+ @ hls_schema [
43+ storage_dir: [
44+ type: :string ,
45+ default: "/tmp/shinkai/hls"
46+ ] ,
47+ max_segments: [
48+ type: :non_neg_integer ,
49+ default: 7 ,
50+ doc: "Max segments to keep in live playlists"
51+ ] ,
52+ segment_duration: [
53+ type: :non_neg_integer ,
54+ default: 2000
55+ ] ,
56+ part_duration: [
57+ type: :non_neg_integer ,
58+ default: 300
1859 ] ,
19- hls: [
20- storage_dir: "/tmp/shinkai/hls" ,
21- max_segments: 7 ,
22- segment_duration: 2_000 ,
23- part_duration: 500 ,
24- segment_type: :fmp4
60+ segment_type: [
61+ type: { :custom , __MODULE__ , :validate_hls_segment_type , [ ] } ,
62+ default: :fmp4
2563 ]
2664 ]
2765
@@ -48,10 +86,10 @@ defmodule Shinkai.Config do
4886
4987 app_configs = Enum . map ( @ top_level_keys , & { & 1 , Application . get_env ( :shinkai , & 1 , [ ] ) } )
5088
51- Enum . map ( @ default_config , fn { key , config } ->
52- config
89+ Enum . map ( @ top_level_keys , fn key ->
90+ [ ]
5391 |> Keyword . merge ( app_configs [ key ] )
54- |> Keyword . merge ( user_config [ key ] || [ ] )
92+ |> Keyword . merge ( user_config [ key ] )
5593 |> then ( & { key , & 1 } )
5694 end )
5795 end
@@ -80,7 +118,9 @@ defmodule Shinkai.Config do
80118
81119 case Map . keys ( config ) -- keys do
82120 [ ] ->
83- Enum . map ( config , fn { key , value } -> { String . to_atom ( key ) , value } end )
121+ @ top_level_keys
122+ |> Enum . map ( & { & 1 , [ ] } )
123+ |> Keyword . merge ( Enum . map ( config , fn { key , value } -> { String . to_atom ( key ) , value } end ) )
84124
85125 invalid_keys ->
86126 raise ArgumentError , """
@@ -96,128 +136,43 @@ defmodule Shinkai.Config do
96136 defp parse_and_validate ( [ ] , acc ) , do: acc
97137
98138 defp parse_and_validate ( [ { :hls , hls_config } | rest ] , acc ) do
99- hls_config = parse_and_validate_hls ( hls_config )
139+ hls_config = do_parse_and_validate ( hls_config , @ hls_schema )
100140 parse_and_validate ( rest , [ { :hls , hls_config } | acc ] )
101141 end
102142
103143 defp parse_and_validate ( [ { :server , server_config } | rest ] , acc ) do
104- server_config = parse_and_validate_server ( server_config )
144+ server_config = do_parse_and_validate ( server_config , @ server_schema )
105145 parse_and_validate ( rest , [ { :server , server_config } | acc ] )
106146 end
107147
108148 defp parse_and_validate ( [ { :rtmp , rtmp_config } | rest ] , acc ) do
109- rtmp_config = parse_and_validate_rtmp ( rtmp_config )
149+ rtmp_config = do_parse_and_validate ( rtmp_config , @ rtmp_schema )
110150 parse_and_validate ( rest , [ { :rtmp , rtmp_config } | acc ] )
111151 end
112152
113- defp parse_and_validate_hls ( config , acc \\ [ ] )
153+ defp do_parse_and_validate ( config , schame ) do
154+ config = config || [ ]
114155
115- defp parse_and_validate_hls ( nil , _acc ) , do: [ ]
116- defp parse_and_validate_hls ( [ ] , acc ) , do: acc
156+ cond do
157+ Keyword . keyword? ( config ) ->
158+ NimbleOptions . validate! ( config , schame )
117159
118- defp parse_and_validate_hls ( config , acc ) when is_map ( config ) do
119- parse_and_validate_hls ( Map . to_list ( config ) , acc )
120- end
121-
122- defp parse_and_validate_hls ( [ { :segment_type , value } | rest ] , acc )
123- when value in [ :fmp4 , :mpeg_ts , :low_latency ] do
124- parse_and_validate_hls ( rest , [ { :segment_type , value } | acc ] )
125- end
126-
127- defp parse_and_validate_hls ( [ { "segment_type" , value } | rest ] , acc )
128- when value in [ "fmp4" , "mpeg_ts" , "low_latency" ] do
129- parse_and_validate_hls ( rest , [ { :segment_type , String . to_atom ( value ) } | acc ] )
130- end
131-
132- defp parse_and_validate_hls ( [ { key , value } | rest ] , acc )
133- when key in [ "segment_duration" , :segment_duration ] and is_integer ( value ) and value >= 1000 do
134- parse_and_validate_hls ( rest , [ { :segment_duration , value } | acc ] )
135- end
136-
137- defp parse_and_validate_hls ( [ { key , value } | rest ] , acc )
138- when key in [ "max_segments" , :max_segments ] and is_integer ( value ) and value > 3 do
139- parse_and_validate_hls ( rest , [ { :max_segments , value } | acc ] )
140- end
160+ is_map ( config ) ->
161+ config
162+ |> Keyword . new ( fn { k , v } -> { String . to_existing_atom ( k ) , v } end )
163+ |> NimbleOptions . validate! ( schame )
141164
142- defp parse_and_validate_hls ( [ { key , value } | rest ] , acc )
143- when key in [ "part_duration" , :part_duration ] and is_integer ( value ) and value >= 100 and
144- value < 1000 do
145- parse_and_validate_hls ( rest , [ { :part_duration , value } | acc ] )
146- end
147-
148- defp parse_and_validate_hls ( [ { key , value } | rest ] , acc )
149- when key in [ "storage_dir" , :storage_dir ] do
150- parse_and_validate_hls ( rest , [ { :storage_dir , value } | acc ] )
151- end
152-
153- defp parse_and_validate_hls ( [ { key , value } | _rest ] , _acc ) do
154- raise ArgumentError , """
155- Invalid HLS configuration key or value detected.
156- Key: #{ inspect ( key ) } , Value: #{ inspect ( value ) } .
157- """
158- end
159-
160- defp parse_and_validate_hls ( config , _acc ) do
161- raise ArgumentError , """
162- Invalid HLS configuration format detected.
163- Config: #{ inspect ( config ) } .
164- """
165- end
166-
167- # HTTP server
168- defp parse_and_validate_server ( config , acc \\ [ ] )
169- defp parse_and_validate_server ( nil , _acc ) , do: [ ]
170- defp parse_and_validate_server ( [ ] , acc ) , do: acc
171-
172- defp parse_and_validate_server ( config , acc ) when is_map ( config ) do
173- parse_and_validate_server ( Map . to_list ( config ) , acc )
174- end
175-
176- defp parse_and_validate_server ( [ { key , value } | rest ] , acc )
177- when key in [ "enabled" , :enabled ] and is_boolean ( value ) do
178- parse_and_validate_server ( rest , [ { :enabled , value } | acc ] )
179- end
180-
181- defp parse_and_validate_server ( [ { key , value } | rest ] , acc )
182- when key in [ :port , "port" ] and is_integer ( value ) and value > 0 and value < 65_536 do
183- parse_and_validate_server ( rest , [ { :port , value } | acc ] )
184- end
185-
186- defp parse_and_validate_server ( [ { key , value } | rest ] , acc )
187- when key in [ "certfile" , "keyfile" , :certfile , :keyfile ] do
188- parse_and_validate_server ( rest , [ { String . to_atom ( key ) , value } | acc ] )
189- end
190-
191- defp parse_and_validate_server ( [ { key , value } | _rest ] , _acc ) do
192- raise ArgumentError , """
193- Invalid Server configuration key or value detected.
194- Key: #{ inspect ( key ) } , Value: #{ inspect ( value ) } .
195- """
196- end
197-
198- # RTMP
199- defp parse_and_validate_rtmp ( config , acc \\ [ ] )
200- defp parse_and_validate_rtmp ( nil , _acc ) , do: [ ]
201- defp parse_and_validate_rtmp ( [ ] , acc ) , do: acc
202-
203- defp parse_and_validate_rtmp ( config , acc ) when is_map ( config ) do
204- parse_and_validate_rtmp ( Map . to_list ( config ) , acc )
205- end
206-
207- defp parse_and_validate_rtmp ( [ { key , value } | rest ] , acc )
208- when key in [ "enabled" , :enabled ] and is_boolean ( value ) do
209- parse_and_validate_rtmp ( rest , [ { :enabled , value } | acc ] )
210- end
211-
212- defp parse_and_validate_rtmp ( [ { key , value } | rest ] , acc )
213- when key in [ :port , "port" ] and is_integer ( value ) and value > 0 and value < 65_536 do
214- parse_and_validate_rtmp ( rest , [ { :port , value } | acc ] )
165+ true ->
166+ raise "Expected a map or keyword list received: #{ inspect ( config ) } "
167+ end
215168 end
216169
217- defp parse_and_validate_rtmp ( [ { key , value } | _rest ] , _acc ) do
218- raise ArgumentError , """
219- Invalid RTMP configuration key or value detected.
220- Key: #{ inspect ( key ) } , Value: #{ inspect ( value ) } .
221- """
170+ @ doc false
171+ def validate_hls_segment_type ( value ) do
172+ cond do
173+ value in [ :mpeg_ts , :fmp4 , :low_latency ] -> { :ok , value }
174+ value in [ "mpeg_ts" , "fmp4" , "low_latency" ] -> { :ok , String . to_atom ( value ) }
175+ true -> { :error , value }
176+ end
222177 end
223178end
0 commit comments