dylanplummer commited on
Commit
50019e0
·
1 Parent(s): 4d03e81

add progress and inference options

Browse files
Files changed (2) hide show
  1. app.py +183 -55
  2. hls_download.py +2 -2
app.py CHANGED
@@ -4,6 +4,7 @@ from PIL import Image
4
  import os
5
  import cv2
6
  import math
 
7
  import json
8
  import subprocess
9
  import matplotlib
@@ -29,14 +30,14 @@ from hls_download import download_clips
29
 
30
  #plt.style.use('dark_background')
31
 
32
- LOCAL = False
33
  IMG_SIZE = 256
34
  CACHE_API_CALLS = False
35
  os.makedirs(os.path.join(os.getcwd(), 'clips'), exist_ok=True)
36
-
37
- onnx_file = hf_hub_download(repo_id="lumos-motion/nextjump", filename="nextjump_256.onnx", repo_type="model", token=os.environ['DATASET_SECRET'])
38
-
39
- #onnx_file = 'nextjump.onnx'
40
 
41
  if torch.cuda.is_available():
42
  print("Using CUDA")
@@ -80,44 +81,102 @@ def sigmoid(x):
80
  return 1 / (1 + np.exp(-x))
81
 
82
 
83
- def detect_beeps(video_path, event_length=30, beep_height=0.8):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  reference_file = 'beep.WAV'
85
  fs, beep = wavfile.read(reference_file)
86
  beep = beep[:, 0] + beep[:, 1] # combine stereo to mono
 
 
87
  video = cv2.VideoCapture(video_path)
 
 
 
 
88
  try:
89
  os.remove('temp.wav')
90
  except FileNotFoundError:
91
  pass
 
 
92
  audio_convert_command = f'ffmpeg -i {video_path} -vn -acodec pcm_s16le -ar {fs} -ac 2 temp.wav'
93
  subprocess.call(audio_convert_command, shell=True)
94
- length = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
95
- fps = int(video.get(cv2.CAP_PROP_FPS))
96
- audio = wavfile.read('temp.wav')[1]
97
  audio = (audio[:, 0] + audio[:, 1]) / 2 # combine stereo to mono
 
 
98
  corr = correlate(audio, beep, mode='same') / audio.size
99
- # min max scale to -1, 1
 
100
  corr = 2 * (corr - np.min(corr)) / (np.max(corr) - np.min(corr)) - 1
101
- event_start = length
102
- while length - event_start < fps * event_length:
103
- peaks, _ = find_peaks(corr, height=beep_height, distance=fs)
104
- event_start = int(peaks[0] / fs * fps)
105
- event_end = int(peaks[-1] / fs * fps)
106
- if event_end == event_start:
107
- event_end = event_start + fps * event_length
108
- beep_height -= 0.1
109
- if beep_height <= 0.1:
110
- event_start = 0
111
- event_end = length
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  break
113
- #peaks, _ = find_peaks(corr, height=0.7, distance=fs)
114
- #event_start = int(peaks[0] / fs * fps)
115
- #event_end = int(peaks[-1] / fs * fps)
116
- # plt.plot(corr)
117
- # plt.plot(peaks, corr[peaks], "x")
118
- # plt.savefig('beep.png')
119
- # plt.close()
120
-
 
 
 
 
 
 
 
 
 
 
121
  return event_start, event_end
122
 
123
 
@@ -236,16 +295,47 @@ def detect_relay_beeps(video_path, event_start, relay_length=30, n_jumpers=4, be
236
  return starts, ends
237
 
238
 
239
- def inference(in_video, stream_url, start_time, end_time, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay,
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  count_only_api, api_key, seq_len=64, stride_length=32, stride_pad=3, batch_size=4,
241
  miss_threshold=0.8, marks_threshold=0.5, median_pred_filter=True, both_feet=True,
242
  api_call=False,
243
  progress=gr.Progress()):
244
- progress(0, desc="Downloading clip...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  if in_video is None:
246
- in_video = download_clips(stream_url, os.path.join(os.getcwd(), 'clips'), start_time, end_time)
247
  else: # local uploaded video (still resize with ffmpeg)
248
- in_video = download_clips(in_video, os.path.join(os.getcwd(), 'clips'), start_time, end_time)
249
  progress(0, desc="Running inference...")
250
  has_access = False
251
  if api_call:
@@ -283,14 +373,15 @@ def inference(in_video, stream_url, start_time, end_time, beep_detection_on, eve
283
  frame = cv2.cvtColor(np.uint8(frame), cv2.COLOR_BGR2RGB)
284
  # add square padding with opencv
285
  #frame = square_pad_opencv(frame)
286
- frame_center_x = frame.shape[1] // 2
287
- frame_center_y = frame.shape[0] // 2
288
- frame = cv2.resize(frame, (0, 0), fx=resize_amount, fy=resize_amount, interpolation=cv2.INTER_CUBIC)
289
- frame_center_x = frame.shape[1] // 2
290
- frame_center_y = frame.shape[0] // 2
291
- crop_x = frame_center_x - IMG_SIZE // 2
292
- crop_y = frame_center_y - IMG_SIZE // 2
293
- frame = frame[crop_y:crop_y+IMG_SIZE, crop_x:crop_x+IMG_SIZE]
 
294
  all_frames.append(frame)
295
 
296
  cap.release()
@@ -310,8 +401,8 @@ def inference(in_video, stream_url, start_time, end_time, beep_detection_on, eve
310
  batch_list = []
311
  idx_list = []
312
  inference_futures = []
313
- with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
314
- for i in range(0, length + stride_length - stride_pad, stride_length):
315
  batch = all_frames[i:i + seq_len]
316
  Xlist = []
317
  preprocess_tasks = [(idx, executor.submit(preprocess_image, img, IMG_SIZE)) for idx, img in enumerate(batch)]
@@ -339,25 +430,31 @@ def inference(in_video, stream_url, start_time, end_time, beep_detection_on, eve
339
  idx_list.append(idx_list[-1])
340
  future = executor.submit(run_inference, batch_list)
341
  inference_futures.append((batch_list, idx_list, future))
342
-
343
  # Collect and process the inference results
344
- for batch_list, idx_list, future in tqdm(inference_futures):
345
  outputs = future.result()
346
  y1_out = outputs[0]
347
  y2_out = outputs[1]
348
  y3_out = outputs[2]
349
  y4_out = outputs[3]
350
  y5_out = outputs[4]
351
- y6_out = outputs[5]
 
 
 
352
  for y1, y2, y3, y4, y5, y6, idx in zip(y1_out, y2_out, y3_out, y4_out, y5_out, y6_out, idx_list):
353
- periodLength = y1.squeeze()
354
  periodicity = y2.squeeze()
355
  marks = y3.squeeze()
356
  event_type = y4.squeeze()
357
  foot_type = y5.squeeze()
358
  phase = y6.squeeze()
359
  period_lengths[idx:idx+seq_len] += periodLength[:, 0]
360
- period_lengths_rope[idx:idx+seq_len] += periodLength[:, 1]
 
 
 
361
  periodicities[idx:idx+seq_len] += periodicity
362
  full_marks[idx:idx+seq_len] += marks
363
  event_type_logits[idx:idx+seq_len] += event_type
@@ -404,16 +501,24 @@ def inference(in_video, stream_url, start_time, end_time, beep_detection_on, eve
404
  periodicity_mask = np.int32(periodicity > miss_threshold)
405
  numofReps = 0
406
  count = []
 
 
407
  for i in range(len(periodLength)):
408
  if periodLength[i] < 2 or periodicity_mask[i] == 0:
409
  numofReps += 0
 
 
 
 
410
  elif full_marks_mask[i]: # high confidence mark detected
411
  if math.modf(numofReps)[0] < 0.2: # probably false positive/late detection
412
  numofReps = float(int(numofReps))
413
  else:
414
  numofReps = float(int(numofReps) + 1.01) # round up
 
415
  else:
416
  numofReps += max(0, periodicity_mask[i]/(periodLength[i]))
 
417
  count.append(round(float(numofReps), 2))
418
  count_pred = count[-1]
419
  marks_count_pred = 0
@@ -697,13 +802,36 @@ with gr.Blocks() as demo:
697
  max_length=300)
698
  with gr.Row():
699
  with gr.Column():
 
 
 
 
 
 
 
700
  in_stream_url = gr.Textbox(label="Stream URL", elem_id='stream-url', visible=True)
701
-
702
- in_stream_start = gr.Textbox(label="Start Time", elem_id='stream-start', visible=True, value='00:00:00')
703
-
704
  in_stream_start = gr.Textbox(label="Start Time", elem_id='stream-start', visible=True, value='00:00:00')
705
  in_stream_end = gr.Textbox(label="End Time", elem_id='stream-end', visible=True)
706
  with gr.Column():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  beep_detection_on = gr.Checkbox(label="Detect Beeps", elem_id='detect-beeps', visible=True)
708
  event_length = gr.Textbox(label="Expected Event Length (s)", elem_id='event-length', visible=True)
709
  relay_detection_on = gr.Checkbox(label="Relay Event", elem_id='relay-beeps', visible=True)
@@ -740,19 +868,19 @@ with gr.Blocks() as demo:
740
 
741
  demo_inference = partial(inference, count_only_api=False, api_key=None)
742
 
743
- run_button.click(demo_inference, [in_video, in_stream_url, in_stream_start, in_stream_end, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay],
744
  outputs=[out_video, out_text, out_plot, out_phase_spiral, out_phase, out_hist, out_event_type_dist])
745
  api_inference = partial(inference, api_call=True)
746
- api_dummy_button.click(api_inference, [in_video, in_stream_url, in_stream_start, in_stream_end, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay, count_only, api_token],
747
  outputs=[period_length], api_name='inference')
748
  examples = [
749
  #['https://hiemdall-dev2.azurewebsites.net/api/clip/clp_vrpWTyjM/mp4', '00:00:00', '00:01:10', True, 60],
750
- ['files/wc2023.mp4', '', '00:00:00', '', True, 30, False, '30', '0.2'],
751
  #['https://hiemdall-dev2.azurewebsites.net/api/playlist/rec_rd2FAyUo/vod', '01:24:22', '01:25:35', True, 60]
752
  #['https://hiemdall-dev2.azurewebsites.net/api/playlist/rec_PY5Ukaua/vod, '00:52:53', '00:55:00', True, 120]
753
  ]
754
  gr.Examples(examples,
755
- inputs=[in_video, in_stream_url, in_stream_start, in_stream_end, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay],
756
  outputs=[out_video, out_text, out_plot, out_phase_spiral, out_phase, out_hist, out_event_type_dist],
757
  fn=demo_inference, cache_examples=False)
758
 
 
4
  import os
5
  import cv2
6
  import math
7
+ import time
8
  import json
9
  import subprocess
10
  import matplotlib
 
30
 
31
  #plt.style.use('dark_background')
32
 
33
+ LOCAL = True
34
  IMG_SIZE = 256
35
  CACHE_API_CALLS = False
36
  os.makedirs(os.path.join(os.getcwd(), 'clips'), exist_ok=True)
37
+ current_model = 'nextjump_speed'
38
+ #onnx_file = hf_hub_download(repo_id="lumos-motion/nextjump", filename=f"{current_model}.onnx", repo_type="model", token=os.environ['DATASET_SECRET'])
39
+ onnx_file = f'{current_model}.onnx'
40
+ api = HfApi()
41
 
42
  if torch.cuda.is_available():
43
  print("Using CUDA")
 
81
  return 1 / (1 + np.exp(-x))
82
 
83
 
84
+ def detect_beeps(video_path, target_event_length=30, beep_height=0.8):
85
+ """
86
+ Detects beep sounds in a video file and returns frame indices for start and end points.
87
+ Finds the pair of peaks that are closest to the target event length.
88
+
89
+ Args:
90
+ video_path: Path to the video file
91
+ target_event_length: Target duration of the event in seconds
92
+ beep_height: Initial threshold for peak detection
93
+
94
+ Returns:
95
+ event_start: Frame index for the start of the event
96
+ event_end: Frame index for the end of the event
97
+ """
98
+
99
+ # Read reference beep
100
  reference_file = 'beep.WAV'
101
  fs, beep = wavfile.read(reference_file)
102
  beep = beep[:, 0] + beep[:, 1] # combine stereo to mono
103
+
104
+ # Open video file
105
  video = cv2.VideoCapture(video_path)
106
+ length = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
107
+ fps = int(video.get(cv2.CAP_PROP_FPS))
108
+
109
+ # Clean up any previous temporary files
110
  try:
111
  os.remove('temp.wav')
112
  except FileNotFoundError:
113
  pass
114
+
115
+ # Extract audio from video
116
  audio_convert_command = f'ffmpeg -i {video_path} -vn -acodec pcm_s16le -ar {fs} -ac 2 temp.wav'
117
  subprocess.call(audio_convert_command, shell=True)
118
+
119
+ # Read the extracted audio
120
+ _, audio = wavfile.read('temp.wav')
121
  audio = (audio[:, 0] + audio[:, 1]) / 2 # combine stereo to mono
122
+
123
+ # Cross-correlate with the reference beep
124
  corr = correlate(audio, beep, mode='same') / audio.size
125
+
126
+ # Min-max scale correlation to [-1, 1]
127
  corr = 2 * (corr - np.min(corr)) / (np.max(corr) - np.min(corr)) - 1
128
+
129
+ # Target number of frames for the event
130
+ target_frames = fps * target_event_length
131
+
132
+ # Strategy: Try different height thresholds to find peaks,
133
+ # then select the pair closest to the target length
134
+ best_pair = None
135
+ best_diff = float('inf')
136
+
137
+ min_height = 0.3 # Minimum threshold to consider
138
+ height_step = 0.05 # Decrease step
139
+
140
+ # Try different height thresholds
141
+ current_height = beep_height
142
+ while current_height >= min_height:
143
+ peaks, _ = find_peaks(corr, height=current_height, distance=fs//2)
144
+
145
+ if len(peaks) >= 2:
146
+ # Check all possible pairs of peaks
147
+ for i in range(len(peaks)):
148
+ for j in range(i+1, len(peaks)):
149
+ start_frame = int(peaks[i] / fs * fps)
150
+ end_frame = int(peaks[j] / fs * fps)
151
+ duration = end_frame - start_frame
152
+
153
+ # Calculate how close this pair is to the target length
154
+ diff = abs(duration - target_frames)
155
+
156
+ # Update if this is the best match so far
157
+ if diff < best_diff:
158
+ best_diff = diff
159
+ best_pair = (start_frame, end_frame)
160
+ if best_diff < 15: # If we found a good pair, break early
161
  break
162
+
163
+ # Reduce height threshold and try again
164
+ current_height -= height_step
165
+
166
+ # If we found a good pair, use it
167
+ if best_pair:
168
+ event_start, event_end = best_pair
169
+ else:
170
+ # Fallback: use the whole video
171
+ event_start = 0
172
+ event_end = length
173
+
174
+ # Optional visualization (commented out)
175
+ plt.plot(corr)
176
+ plt.plot(peaks, corr[peaks], "x")
177
+ plt.savefig('beep.png')
178
+ plt.close()
179
+
180
  return event_start, event_end
181
 
182
 
 
295
  return starts, ends
296
 
297
 
298
+ def upload_video(out_text, in_video):
299
+ if out_text != '':
300
+ # generate a timestamp name for the video
301
+ upload_path = f"{int(time.time())}.mp4"
302
+ api.upload_file(
303
+ path_or_fileobj=in_video,
304
+ path_in_repo=upload_path,
305
+ repo_id="lumos-motion/single-rope-contest",
306
+ repo_type="dataset",
307
+ )
308
+
309
+
310
+ def inference(in_video, stream_url, start_time, end_time, use_60fps, model_choice,
311
+ beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay,
312
  count_only_api, api_key, seq_len=64, stride_length=32, stride_pad=3, batch_size=4,
313
  miss_threshold=0.8, marks_threshold=0.5, median_pred_filter=True, both_feet=True,
314
  api_call=False,
315
  progress=gr.Progress()):
316
+ global current_model
317
+ if model_choice != current_model:
318
+ current_model = model_choice
319
+ onnx_file = hf_hub_download(repo_id="lumos-motion/nextjump", filename=f"{current_model}.onnx", repo_type="model", token=os.environ['DATASET_SECRET'])
320
+
321
+
322
+ if torch.cuda.is_available():
323
+ print("Using CUDA")
324
+ providers = [("CUDAExecutionProvider", {"device_id": torch.cuda.current_device(),
325
+ "user_compute_stream": str(torch.cuda.current_stream().cuda_stream)})]
326
+ sess_options = ort.SessionOptions()
327
+ #sess_options.log_severity_level = 0
328
+ ort_sess = ort.InferenceSession(onnx_file, sess_options=sess_options, providers=providers)
329
+ else:
330
+ print("Using CPU")
331
+ ort_sess = ort.InferenceSession(onnx_file)
332
+
333
+ # warmup inference
334
+ ort_sess.run(None, {'video': np.zeros((4, 64, 3, IMG_SIZE, IMG_SIZE), dtype=np.float32)})
335
  if in_video is None:
336
+ in_video = download_clips(stream_url, os.path.join(os.getcwd(), 'clips'), start_time, end_time, use_60fps=use_60fps)
337
  else: # local uploaded video (still resize with ffmpeg)
338
+ in_video = download_clips(in_video, os.path.join(os.getcwd(), 'clips'), start_time, end_time, use_60fps=use_60fps)
339
  progress(0, desc="Running inference...")
340
  has_access = False
341
  if api_call:
 
373
  frame = cv2.cvtColor(np.uint8(frame), cv2.COLOR_BGR2RGB)
374
  # add square padding with opencv
375
  #frame = square_pad_opencv(frame)
376
+ # frame_center_x = frame.shape[1] // 2
377
+ # frame_center_y = frame.shape[0] // 2
378
+ # frame = cv2.resize(frame, (0, 0), fx=resize_amount, fy=resize_amount, interpolation=cv2.INTER_CUBIC)
379
+ # frame_center_x = frame.shape[1] // 2
380
+ # frame_center_y = frame.shape[0] // 2
381
+ # crop_x = frame_center_x - IMG_SIZE // 2
382
+ # crop_y = frame_center_y - IMG_SIZE // 2
383
+ # frame = frame[crop_y:crop_y+IMG_SIZE, crop_x:crop_x+IMG_SIZE]
384
+ frame = cv2.resize(frame, (IMG_SIZE, IMG_SIZE), interpolation=cv2.INTER_CUBIC)
385
  all_frames.append(frame)
386
 
387
  cap.release()
 
401
  batch_list = []
402
  idx_list = []
403
  inference_futures = []
404
+ with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
405
+ for i in progress.tqdm(range(0, length + stride_length - stride_pad, stride_length)):
406
  batch = all_frames[i:i + seq_len]
407
  Xlist = []
408
  preprocess_tasks = [(idx, executor.submit(preprocess_image, img, IMG_SIZE)) for idx, img in enumerate(batch)]
 
430
  idx_list.append(idx_list[-1])
431
  future = executor.submit(run_inference, batch_list)
432
  inference_futures.append((batch_list, idx_list, future))
433
+ progress(0, desc="Processing results...")
434
  # Collect and process the inference results
435
+ for batch_list, idx_list, future in progress.tqdm(tqdm(inference_futures)):
436
  outputs = future.result()
437
  y1_out = outputs[0]
438
  y2_out = outputs[1]
439
  y3_out = outputs[2]
440
  y4_out = outputs[3]
441
  y5_out = outputs[4]
442
+ try:
443
+ y6_out = outputs[5]
444
+ except IndexError:
445
+ y6_out = np.zeros((len(batch_list), seq_len, 2))
446
  for y1, y2, y3, y4, y5, y6, idx in zip(y1_out, y2_out, y3_out, y4_out, y5_out, y6_out, idx_list):
447
+ periodLength = y1
448
  periodicity = y2.squeeze()
449
  marks = y3.squeeze()
450
  event_type = y4.squeeze()
451
  foot_type = y5.squeeze()
452
  phase = y6.squeeze()
453
  period_lengths[idx:idx+seq_len] += periodLength[:, 0]
454
+ try:
455
+ period_lengths_rope[idx:idx+seq_len] += periodLength[:, 1]
456
+ except IndexError:
457
+ period_lengths_rope[idx:idx+seq_len] += periodLength[:, 0]
458
  periodicities[idx:idx+seq_len] += periodicity
459
  full_marks[idx:idx+seq_len] += marks
460
  event_type_logits[idx:idx+seq_len] += event_type
 
501
  periodicity_mask = np.int32(periodicity > miss_threshold)
502
  numofReps = 0
503
  count = []
504
+ miss_detected = True
505
+ num_misses = 0
506
  for i in range(len(periodLength)):
507
  if periodLength[i] < 2 or periodicity_mask[i] == 0:
508
  numofReps += 0
509
+ if not miss_detected:
510
+ miss_detected = True
511
+ num_misses += 1
512
+ numofReps -= 2
513
  elif full_marks_mask[i]: # high confidence mark detected
514
  if math.modf(numofReps)[0] < 0.2: # probably false positive/late detection
515
  numofReps = float(int(numofReps))
516
  else:
517
  numofReps = float(int(numofReps) + 1.01) # round up
518
+ miss_detected = False
519
  else:
520
  numofReps += max(0, periodicity_mask[i]/(periodLength[i]))
521
+ miss_detected = False
522
  count.append(round(float(numofReps), 2))
523
  count_pred = count[-1]
524
  marks_count_pred = 0
 
802
  max_length=300)
803
  with gr.Row():
804
  with gr.Column():
805
+ gr.Markdown(
806
+ """
807
+ ### Stream Input Options
808
+ Either upload a video file above, or provide a stream URL below.
809
+ """,
810
+ elem_id='stream-input-options',
811
+ )
812
  in_stream_url = gr.Textbox(label="Stream URL", elem_id='stream-url', visible=True)
 
 
 
813
  in_stream_start = gr.Textbox(label="Start Time", elem_id='stream-start', visible=True, value='00:00:00')
814
  in_stream_end = gr.Textbox(label="End Time", elem_id='stream-end', visible=True)
815
  with gr.Column():
816
+ gr.Markdown(
817
+ """
818
+ ### Inference Options
819
+ Select the model and framerate for inference.
820
+ """,
821
+ elem_id='inference-options',
822
+ )
823
+ use_60fps = gr.Checkbox(label="Use 60 FPS", elem_id='use-60fps', visible=True)
824
+ model_choice = gr.Dropdown(
825
+ ["nextjump_speed", "nextjump_all", "nextjump_both_feet"], label="Model Choice", info="For now just speed-only or general model",
826
+ )
827
+ with gr.Column():
828
+ gr.Markdown(
829
+ """
830
+ ### Beep Detection Options
831
+ Must be using official IJRU timing tracks.
832
+ """,
833
+ elem_id='beep-detection-options',
834
+ )
835
  beep_detection_on = gr.Checkbox(label="Detect Beeps", elem_id='detect-beeps', visible=True)
836
  event_length = gr.Textbox(label="Expected Event Length (s)", elem_id='event-length', visible=True)
837
  relay_detection_on = gr.Checkbox(label="Relay Event", elem_id='relay-beeps', visible=True)
 
868
 
869
  demo_inference = partial(inference, count_only_api=False, api_key=None)
870
 
871
+ run_button.click(demo_inference, [in_video, in_stream_url, in_stream_start, in_stream_end, use_60fps, model_choice, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay],
872
  outputs=[out_video, out_text, out_plot, out_phase_spiral, out_phase, out_hist, out_event_type_dist])
873
  api_inference = partial(inference, api_call=True)
874
+ api_dummy_button.click(api_inference, [in_video, in_stream_url, in_stream_start, in_stream_end, use_60fps, model_choice, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay, count_only, api_token],
875
  outputs=[period_length], api_name='inference')
876
  examples = [
877
  #['https://hiemdall-dev2.azurewebsites.net/api/clip/clp_vrpWTyjM/mp4', '00:00:00', '00:01:10', True, 60],
878
+ ['files/wc2023.mp4', '', '00:00:00', '', True, 'nextjump_speed', True, 30, False, '30', '0.2'],
879
  #['https://hiemdall-dev2.azurewebsites.net/api/playlist/rec_rd2FAyUo/vod', '01:24:22', '01:25:35', True, 60]
880
  #['https://hiemdall-dev2.azurewebsites.net/api/playlist/rec_PY5Ukaua/vod, '00:52:53', '00:55:00', True, 120]
881
  ]
882
  gr.Examples(examples,
883
+ inputs=[in_video, in_stream_url, in_stream_start, in_stream_end, use_60fps, model_choice, beep_detection_on, event_length, relay_detection_on, relay_length, switch_delay],
884
  outputs=[out_video, out_text, out_plot, out_phase_spiral, out_phase, out_hist, out_event_type_dist],
885
  fn=demo_inference, cache_examples=False)
886
 
hls_download.py CHANGED
@@ -1,7 +1,7 @@
1
  import subprocess
2
  import os
3
 
4
- def download_clips(stream_url, out_dir, start_time, end_time, resize=True):
5
  # remove all .mp4 files in out_dir to avoid confusion
6
  if len(os.listdir(out_dir)) > 5:
7
  for f in os.listdir(out_dir):
@@ -14,7 +14,7 @@ def download_clips(stream_url, out_dir, start_time, end_time, resize=True):
14
  '-i', stream_url,
15
  '-c:v', 'libx264',
16
  '-crf', '23',
17
- '-r', '30',
18
  '-maxrate', '2M',
19
  '-bufsize', '4M',
20
  '-vf', f"scale=-2:300",
 
1
  import subprocess
2
  import os
3
 
4
+ def download_clips(stream_url, out_dir, start_time, end_time, resize=True, use_60fps=False):
5
  # remove all .mp4 files in out_dir to avoid confusion
6
  if len(os.listdir(out_dir)) > 5:
7
  for f in os.listdir(out_dir):
 
14
  '-i', stream_url,
15
  '-c:v', 'libx264',
16
  '-crf', '23',
17
+ '-r', '30' if not use_60fps else '60',
18
  '-maxrate', '2M',
19
  '-bufsize', '4M',
20
  '-vf', f"scale=-2:300",