Skip to content

Commit f643e0a

Browse files
committed
Add forward until wide rendering
1 parent 2580278 commit f643e0a

File tree

3 files changed

+163
-30
lines changed

3 files changed

+163
-30
lines changed

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ downloader:
1313
ffmpeg_clip:
1414
python ffmpeg_clip.py "a2a0ccea32023010|2023-07-27--13-01-19" 242 30 -nv -t driver
1515

16+
ffmpeg_clip_fuw:
17+
python ffmpeg_clip.py "a2a0ccea32023010|2023-07-27--13-01-19" 242 30 -nv -t forward_upon_wide
18+
1619
ffmpeg_clip_360:
1720
python ffmpeg_clip.py "a2a0ccea32023010|2023-07-27--13-01-19" 242 30 -nv -t 360
1821

22+
ffmpeg_clip_360_fuw:
23+
python ffmpeg_clip.py "a2a0ccea32023010|2023-07-27--13-01-19" 242 30 -nv -t 360_forward_upon_wide
24+
1925
# These uses a modified cog up one directory.
2026
predict:
2127
./cog/generate.sh
@@ -33,6 +39,14 @@ predict-360:
3339
./cog/generate.sh
3440
../cog/cog predict -i renderType=360
3541

42+
predict-fuw:
43+
./cog/generate.sh
44+
../cog/cog predict -i renderType=forward_upon_wide
45+
46+
predict-360-fuw:
47+
./cog/generate.sh
48+
../cog/cog predict -i renderType=360_forward_upon_wide
49+
3650
# Push using modified cog
3751
push:
3852
./cog/generate.sh

ffmpeg_clip.py

Lines changed: 130 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,17 @@ def make_ffmpeg_clip(
4444
length_seconds: int,
4545
target_mb: int,
4646
nvidia_hardware_rendering: bool,
47+
forward_upon_wide_h: float,
4748
output: str,
4849
):
49-
if render_type not in ["forward", "wide", "driver", "360"]:
50+
if render_type not in [
51+
"forward",
52+
"wide",
53+
"driver",
54+
"360",
55+
"forward_upon_wide",
56+
"360_forward_upon_wide",
57+
]:
5058
raise ValueError(f"Invalid choice: {render_type}")
5159
if not os.path.exists(data_dir):
5260
raise ValueError(f"Invalid data_dir: {data_dir}")
@@ -65,25 +73,35 @@ def make_ffmpeg_clip(
6573
range(start_seconds // 60, (start_seconds + length_seconds) // 60 + 1)
6674
)
6775

76+
# Generate concat strings for clip to use
77+
forward_concat_string_input = "|".join(
78+
[f"{data_dir}/{route_date}--{segment}/fcamera.hevc" for segment in segments]
79+
)
80+
forward_concat_string = f"concat:{forward_concat_string_input}"
81+
wide_concat_string_input = "|".join(
82+
[f"{data_dir}/{route_date}--{segment}/ecamera.hevc" for segment in segments]
83+
)
84+
wide_concat_string = f"concat:{wide_concat_string_input}"
85+
driver_concat_string_input = "|".join(
86+
[f"{data_dir}/{route_date}--{segment}/dcamera.hevc" for segment in segments]
87+
)
88+
driver_concat_string = f"concat:{driver_concat_string_input}"
89+
6890
# Figure out what segments we'll need to concat
6991
# .hevc files can be concatenated with the concat protocol demuxer
7092

7193
# Split processing into two types:
7294
# Simple processing: forward, wide, driver
73-
# Complex processing: 360
95+
# Complex processing: 360, forward_upon_wide, 360_forward_upon_wide
7496
if render_type in ["forward", "wide", "driver"]:
7597
# Map render_type to appropriate filename
7698
if render_type == "forward":
77-
filename = "fcamera.hevc"
99+
ffmpeg_concat_string = forward_concat_string
78100
elif render_type == "wide":
79-
filename = "ecamera.hevc"
101+
ffmpeg_concat_string = wide_concat_string
80102
elif render_type == "driver":
81-
filename = "dcamera.hevc"
82-
# Concat the segments
83-
ffmpeg_concat_string_input = "|".join(
84-
[f"{data_dir}/{route_date}--{segment}/{filename}" for segment in segments]
85-
)
86-
ffmpeg_concat_string = f"concat:{ffmpeg_concat_string_input}"
103+
ffmpeg_concat_string = driver_concat_string
104+
87105
# Run the ffmpeg command
88106
command = [
89107
"ffmpeg",
@@ -130,19 +148,8 @@ def make_ffmpeg_clip(
130148
process.kill()
131149
raise
132150

133-
elif render_type == "360":
134-
# Need to make two concat strings
135-
# One for wide, one for driver
136-
wide_concat_string_input = "|".join(
137-
[f"{data_dir}/{route_date}--{segment}/ecamera.hevc" for segment in segments]
138-
)
139-
wide_concat_string = f"concat:{wide_concat_string_input}"
140-
driver_concat_string_input = "|".join(
141-
[f"{data_dir}/{route_date}--{segment}/dcamera.hevc" for segment in segments]
142-
)
143-
driver_concat_string = f"concat:{driver_concat_string_input}"
144-
145-
# Run the ffmpeg command that has two inputs and fisheye
151+
elif render_type in ["forward_upon_wide"]:
152+
# Run the ffmpeg command
146153
command = [
147154
"ffmpeg",
148155
"-y",
@@ -153,22 +160,110 @@ def make_ffmpeg_clip(
153160
"-r",
154161
"20",
155162
"-i",
156-
driver_concat_string,
163+
wide_concat_string,
157164
"-probesize",
158165
"100M",
159166
"-r",
160167
"20",
161168
"-i",
162-
wide_concat_string,
169+
forward_concat_string,
163170
"-t",
164171
str(length_seconds),
165172
"-ss",
166173
str(start_seconds_relative),
167174
"-filter_complex",
168-
f"[0:v]pad=iw:ih+290:0:290:color=#160000,crop=iw:1208[driver];[driver][1:v]hstack=inputs=2[v];[v]v360=dfisheye:equirect:ih_fov=195:iv_fov=122[vout]",
169-
"-map",
170-
"[vout]",
175+
f"[1:v]scale=iw/4.5:ih/4.5,format=yuva420p,colorchannelmixer=aa=1[front];[0:v][front]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/{forward_upon_wide_h}",
176+
"-f",
177+
"mp4",
178+
"-movflags",
179+
"+faststart",
171180
]
181+
if nvidia_hardware_rendering:
182+
# Use H264 for maximum Discord compatibility
183+
command += ["-c:v", "h264_nvenc"]
184+
185+
# Target bitrate
186+
command += [
187+
"-b:v",
188+
str(target_bps),
189+
]
190+
command += [output]
191+
print(command)
192+
process = subprocess.Popen(command, stdout=subprocess.PIPE)
193+
try:
194+
while True:
195+
proc_output = process.stdout.readline()
196+
if proc_output == b"" and process.poll() is not None:
197+
break
198+
if proc_output:
199+
print(proc_output)
200+
except KeyboardInterrupt:
201+
process.kill()
202+
raise
203+
204+
elif render_type == "360" or render_type == "360_forward_upon_wide":
205+
206+
if render_type == "360":
207+
# Run the ffmpeg command that has two inputs and fisheye
208+
command = [
209+
"ffmpeg",
210+
"-y",
211+
"-hwaccel",
212+
"auto",
213+
"-probesize",
214+
"100M",
215+
"-r",
216+
"20",
217+
"-i",
218+
driver_concat_string,
219+
"-probesize",
220+
"100M",
221+
"-r",
222+
"20",
223+
"-i",
224+
wide_concat_string,
225+
"-t",
226+
str(length_seconds),
227+
"-ss",
228+
str(start_seconds_relative),
229+
"-filter_complex",
230+
f"[0:v]pad=iw:ih+290:0:290:color=#160000,crop=iw:1208[driver];[driver][1:v]hstack=inputs=2[v];[v]v360=dfisheye:equirect:ih_fov=195:iv_fov=122[vout]",
231+
"-map",
232+
"[vout]",
233+
]
234+
elif render_type == "360_forward_upon_wide":
235+
command = [
236+
"ffmpeg",
237+
"-y",
238+
"-hwaccel",
239+
"auto",
240+
"-probesize",
241+
"100M",
242+
"-r",
243+
"20",
244+
"-i",
245+
driver_concat_string,
246+
"-probesize",
247+
"100M",
248+
"-r",
249+
"20",
250+
"-i",
251+
wide_concat_string,
252+
"-probesize",
253+
"100M",
254+
"-r",
255+
"20",
256+
"-i",
257+
forward_concat_string,
258+
"-t",
259+
str(length_seconds),
260+
"-ss",
261+
str(start_seconds_relative),
262+
"-filter_complex",
263+
f"[2:v]scale=iw/4.5:ih/4.5,format=yuva420p,colorchannelmixer=aa=1[front];[1:v][front]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/{forward_upon_wide_h}[fuw];[0:v]pad=iw:ih+290:0:290:color=#160000,crop=iw:1208[driver];[driver][fuw]hstack=inputs=2[v];[v]v360=dfisheye:equirect:ih_fov=195:iv_fov=122[vout]",
264+
"-map",
265+
"[vout]",
266+
]
172267
if nvidia_hardware_rendering:
173268
# Use HEVC encoding for 360 since people aren't looking at these
174269
# directly in Discord anyway.
@@ -238,6 +333,12 @@ def make_ffmpeg_clip(
238333
parser.add_argument(
239334
"--target_mb", type=int, help="Target file size in megabytes", default=25
240335
)
336+
parser.add_argument(
337+
"--forward-upon-wide-h",
338+
type=float,
339+
help="Height of the forward camera in forward upon wide overlay videos",
340+
default=2.2,
341+
)
241342
parser.add_argument(
242343
"--nvidia-hardware-rendering",
243344
"-nv",
@@ -258,5 +359,6 @@ def make_ffmpeg_clip(
258359
length_seconds=args.length_seconds,
259360
target_mb=args.target_mb,
260361
nvidia_hardware_rendering=args.nvidia_hardware_rendering,
362+
forward_upon_wide_h=args.forward_upon_wide_h,
261363
output=args.output,
262364
)

predict.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ def setup(self) -> None:
2424
def predict(
2525
self,
2626
renderType: str = Input(
27-
description="Render Type. UI is slow. Forward, Wide, and Driver are fast transcodes; they are great for quick previews. 360 is slow and requires viewing/uploading the video file in VLC or YouTube to pan around in a 🌐 sphere.",
28-
choices=["ui", "forward", "wide", "driver", "360"],
27+
description="Render Type. UI is slow. Forward, Wide, and Driver are fast transcodes; they are great for quick previews. 360 is slow and requires viewing/uploading the video file in VLC or YouTube to pan around in a 🌐 sphere. Forward Upon Wide roughly overlays Forward on Wide. 360 Forward Upon Wide is 360 with Forward Upon Wide as the forward video.",
28+
choices=[
29+
"ui",
30+
"forward",
31+
"wide",
32+
"driver",
33+
"360",
34+
"forward_upon_wide",
35+
"360_forward_upon_wide",
36+
],
2937
default="ui",
3038
),
3139
route: str = Input(
@@ -59,6 +67,9 @@ def predict(
5967
metric: bool = Input(
6068
description="(UI Render only) Render in metric units (km/h)", default=False
6169
),
70+
forwardUponWideH: float = Input(
71+
description="(Forward Upon Wide Renders only) H-position of the forward video overlay on wide. Different devices can have different offsets from the factory.", ge=1.9, le=2.3, default=2.2
72+
),
6273
fileSize: int = Input(
6374
description="Rough size of clip output in MB.", ge=10, le=100, default=25
6475
),
@@ -162,6 +173,11 @@ def predict(
162173
file_types = ["ecameras"]
163174
elif renderType == "driver":
164175
file_types = ["dcameras"]
176+
# Non-comma.ai origin render types
177+
elif renderType == "forward_upon_wide":
178+
file_types = ["ecameras", "cameras"]
179+
elif renderType == "360_forward_upon_wide":
180+
file_types = ["ecameras", "dcameras", "cameras"]
165181

166182
downloader.downloadSegments(
167183
route_or_segment=route,
@@ -181,6 +197,7 @@ def predict(
181197
length_seconds=lengthSeconds,
182198
target_mb=fileSize,
183199
nvidia_hardware_rendering=True,
200+
forward_upon_wide_h=forwardUponWideH,
184201
output="./shared/cog-clip.mp4",
185202
)
186203

0 commit comments

Comments
 (0)