@@ -3,15 +3,14 @@ use clap::Parser;
33use clapshot_server:: {
44 api_server:: validate_org_http_headers_regex,
55 grpc:: { grpc_client:: prepare_organizer, grpc_server:: make_grpc_server_bind} ,
6- run_clapshot,
6+ run_clapshot, PKG_NAME , PKG_VERSION ,
77 storage:: StorageBackend ,
88 video_pipeline:: IngestUsernameFrom ,
9- PKG_NAME , PKG_VERSION ,
109} ;
1110use http:: Uri ;
12- use indoc:: indoc;
13- use std:: { path:: PathBuf , str:: FromStr , sync:: Arc } ;
11+ use std:: { path:: PathBuf , sync:: Arc , str:: FromStr } ;
1412use tracing:: error;
13+ use indoc:: indoc;
1514
1615mod log;
1716
@@ -32,16 +31,17 @@ mod log;
3231) ]
3332struct Args {
3433 /// Directory for database, /incoming, /videos and /rejected
35- #[ arg( short = 'D' , long, required = true , value_name = "DIR" ) ]
34+ #[ arg( short= 'D' , long, required= true , value_name= "DIR" ) ]
3635 data_dir : PathBuf ,
3736
3837 /// Base URL of the API server, e.g. `https://clapshot.example.com`.
3938 /// This depends on your proxy server, and is usually different from `--host` and `--port`.
40- #[ arg( short = 'U' , long, required = true , value_name = "URL" ) ]
39+ #[ arg( short= 'U' , long, required= true , value_name= "URL" ) ]
4140 url_base : String ,
4241
42+
4343 /// TCP port to listen on
44- #[ arg( short = 'p' , long, default_value_t = 8095 ) ]
44+ #[ arg( short= 'p' , long, default_value_t = 8095 ) ]
4545 port : u16 ,
4646
4747 /// Host to listen on
@@ -50,118 +50,116 @@ struct Args {
5050
5151 /// Allowed CORS Origins, separated by commas.
5252 /// Defaults to the value of `url_base`.
53- #[ arg( long, value_name = "ORIGINS" ) ]
53+ #[ arg( long, value_name= "ORIGINS" ) ]
5454 cors : Option < String > ,
5555
56+
5657 /// Polling interval for incoming folder
57- #[ arg( short = 'P' , long, default_value_t = 3.0 , value_name = "SECONDS" ) ]
58+ #[ arg( short= 'P' , long, default_value_t = 3.0 , value_name= "SECONDS" ) ]
5859 poll : f32 ,
5960
6061 /// Max number of workers for media file processing
6162 /// (0 = number of CPU cores)
62- #[ arg( short, long, default_value_t = 0 , value_name = "NUM" ) ]
63+ #[ arg( short, long, default_value_t = 0 , value_name= "NUM" ) ]
6364 workers : usize ,
6465
6566 /// Target (max) bitrate for transcoding, in Mbps
66- #[ arg( short, long, default_value_t = 2.5 , value_name = "MBITS" ) ]
67+ #[ arg( short, long, default_value_t = 2.5 , value_name= "MBITS" ) ]
6768 bitrate : f32 ,
6869
70+
6971 /// Migrate database to latest version. Makes an automatic backup.
7072 #[ arg( long) ]
7173 migrate : bool ,
7274
75+
7376 /// Log to file instead of stdout
74- #[ arg( short, long, value_name = "FILE" ) ]
77+ #[ arg( short, long, value_name= "FILE" ) ]
7578 log : Option < String > ,
7679
7780 /// Set debug level by repeating (-d = debug, -dd = trace)
7881 #[ arg( short, long, action=clap:: ArgAction :: Count ) ]
7982 debug : u8 ,
8083
8184 // Enable debug mode (same as -v)
85+
8286 /// Log in JSON format
8387 #[ arg( short, long) ]
8488 json : bool ,
8589
90+
8691 /// Use this user id if auth headers are not found.
8792 /// Mainly useful for debugging.
88- #[ arg( long, default_value = "anonymous" , value_name = "USER" ) ]
93+ #[ arg( long, default_value= "anonymous" , value_name= "USER" ) ]
8994 default_user : String ,
9095
9196 /// How to determine username for files in incoming/ folder.
9297 /// 'file-owner' uses filesystem ownership, 'folder-name' uses first subfolder name.
93- #[ arg( long, default_value = "file-owner" , value_name = "METHOD" ) ]
98+ #[ arg( long, default_value= "file-owner" , value_name= "METHOD" ) ]
9499 ingest_username_from : String ,
95100
101+
96102 /// Shell command to start Organizer plugin.
97103 /// The command should block until SIGTERM, and log to stdout/stderr without timestamps.
98104 /// Unless --org-uri is a HTTP(S) URI, the command will get a Unix socket path as an argument when Clapshot server calls it.
99- #[ arg( long, value_name = "CMD" ) ]
100- org_cmd : Option < String > , // TODO: turn into a Vec<String> to allow multiple plugins
105+ #[ arg( long, value_name= "CMD" ) ]
106+ org_cmd : Option < String > , // TODO: turn into a Vec<String> to allow multiple plugins
101107
102108 /// Custom endpoint for srv->org connections.
103109 /// E.g. `/path/to/plugin.sock` or `http://[::1]:50051`
104110 /// If `--org-cmd` is given, this defaults to a temp .sock in datadir.
105- #[ arg( long, value_name = "URI" ) ]
111+ #[ arg( long, value_name= "URI" ) ]
106112 org_in_uri : Option < String > ,
107113
108114 /// Listen in TCP address port for org->srv connections.
109115 /// Default is to use a Unix socket in datadir. E.g. `[::1]:50052`
110- #[ arg( long, value_name = "BIND" ) ]
116+ #[ arg( long, value_name= "BIND" ) ]
111117 org_out_tcp : Option < String > ,
112118
113119 /// Path to custom transcoding script
114- #[ arg(
115- long,
116- value_name = "SCRIPT" ,
117- default_value = "scripts/clapshot-transcode"
118- ) ]
120+ #[ arg( long, value_name="SCRIPT" , default_value="scripts/clapshot-transcode" ) ]
119121 transcode_script : String ,
120122
121123 /// Path to custom thumbnailing script
122- #[ arg(
123- long,
124- value_name = "SCRIPT" ,
125- default_value = "scripts/clapshot-thumbnail"
126- ) ]
124+ #[ arg( long, value_name="SCRIPT" , default_value="scripts/clapshot-thumbnail" ) ]
127125 thumbnail_script : String ,
128126
129127 /// Regular expression to filter HTTP headers passed to Organizer.
130128 /// Only headers matching this pattern will be included in UserSessionData.
131129 /// Case-insensitive matching. Default is disabled for security.
132- #[ arg( long, value_name = "REGEX" , default_value = "^$" ) ]
130+ #[ arg( long, value_name= "REGEX" , default_value= "^$" ) ]
133131 org_http_headers : String ,
134132
135133 /// Storage backend (local or s3-compatible object storage)
136- #[ arg( long, value_name = "BACKEND" , default_value = "local" ) ]
134+ #[ arg( long, value_name= "BACKEND" , default_value= "local" ) ]
137135 storage_backend : String ,
138136
139137 /// S3-compatible endpoint base URL, e.g. https://s3.example.com
140- #[ arg( long, value_name = "URL" ) ]
138+ #[ arg( long, value_name= "URL" ) ]
141139 s3_endpoint : Option < String > ,
142140
143141 /// S3 region (required for S3 backend)
144- #[ arg( long, value_name = "REGION" ) ]
142+ #[ arg( long, value_name= "REGION" ) ]
145143 s3_region : Option < String > ,
146144
147145 /// S3 bucket (required for S3 backend)
148- #[ arg( long, value_name = "BUCKET" ) ]
146+ #[ arg( long, value_name= "BUCKET" ) ]
149147 s3_bucket : Option < String > ,
150148
151149 /// S3 access key (required for S3 backend)
152- #[ arg( long, value_name = "KEY" ) ]
150+ #[ arg( long, value_name= "KEY" ) ]
153151 s3_access_key : Option < String > ,
154152
155153 /// S3 secret key (required for S3 backend)
156- #[ arg( long, value_name = "SECRET" ) ]
154+ #[ arg( long, value_name= "SECRET" ) ]
157155 s3_secret_key : Option < String > ,
158156
159157 /// Path/prefix inside the bucket where media files are stored
160- #[ arg( long, value_name = "PREFIX" , default_value = "videos" ) ]
158+ #[ arg( long, value_name= "PREFIX" , default_value= "videos" ) ]
161159 s3_prefix : String ,
162160
163161 /// Public base URL for accessing the bucket/prefix (used for playback URLs)
164- #[ arg( long, value_name = "URL" ) ]
162+ #[ arg( long, value_name= "URL" ) ]
165163 s3_public_url : Option < String > ,
166164}
167165
@@ -206,8 +204,7 @@ fn main() -> anyhow::Result<()> {
206204 & args. data_dir ,
207205 ) ?;
208206
209- let cors_origins: Vec < String > = args
210- . cors
207+ let cors_origins: Vec < String > = args. cors
211208 . map ( |s| s. split ( ',' ) . map ( |s| s. trim ( ) . to_string ( ) ) . collect ( ) )
212209 . unwrap_or_default ( ) ;
213210
@@ -219,30 +216,18 @@ fn main() -> anyhow::Result<()> {
219216 let storage = match args. storage_backend . as_str ( ) {
220217 "local" => StorageBackend :: local ( args. data_dir . join ( "videos" ) , & url_base) ,
221218 "s3" => {
222- let endpoint = args
223- . s3_endpoint
224- . clone ( )
219+ let endpoint = args. s3_endpoint . clone ( )
225220 . ok_or_else ( || anyhow:: anyhow!( "--s3-endpoint is required for S3 backend" ) ) ?;
226- let region = args
227- . s3_region
228- . clone ( )
221+ let region = args. s3_region . clone ( )
229222 . ok_or_else ( || anyhow:: anyhow!( "--s3-region is required for S3 backend" ) ) ?;
230- let bucket = args
231- . s3_bucket
232- . clone ( )
223+ let bucket = args. s3_bucket . clone ( )
233224 . ok_or_else ( || anyhow:: anyhow!( "--s3-bucket is required for S3 backend" ) ) ?;
234- let access_key = args
235- . s3_access_key
236- . clone ( )
225+ let access_key = args. s3_access_key . clone ( )
237226 . ok_or_else ( || anyhow:: anyhow!( "--s3-access-key is required for S3 backend" ) ) ?;
238- let secret_key = args
239- . s3_secret_key
240- . clone ( )
227+ let secret_key = args. s3_secret_key . clone ( )
241228 . ok_or_else ( || anyhow:: anyhow!( "--s3-secret-key is required for S3 backend" ) ) ?;
242229
243- let public_base_url = args
244- . s3_public_url
245- . clone ( )
230+ let public_base_url = args. s3_public_url . clone ( )
246231 . or_else ( || {
247232 Uri :: from_str ( & endpoint) . ok ( ) . and_then ( |uri| {
248233 let scheme = uri. scheme_str ( ) ?;
@@ -263,10 +248,7 @@ fn main() -> anyhow::Result<()> {
263248 public_base_url,
264249 ) ?
265250 }
266- other => bail ! (
267- "Unknown storage backend '{}'. Valid options: local, s3" ,
268- other
269- ) ,
251+ other => bail ! ( "Unknown storage backend '{}'. Valid options: local, s3" , other) ,
270252 } ;
271253
272254 // Run the server (blocking)
@@ -279,11 +261,7 @@ fn main() -> anyhow::Result<()> {
279261 args. port ,
280262 org_uri,
281263 grpc_server_bind,
282- if args. workers == 0 {
283- num_cpus:: get ( )
284- } else {
285- args. workers
286- } ,
264+ if args. workers == 0 { num_cpus:: get ( ) } else { args. workers } ,
287265 target_bitrate,
288266 default_user,
289267 args. poll ,
@@ -298,4 +276,4 @@ fn main() -> anyhow::Result<()> {
298276 }
299277
300278 Ok ( ( ) )
301- }
279+ }
0 commit comments