Spaces:
Running
Running
Mark Duppenthaler
commited on
Commit
·
013aff2
1
Parent(s):
08dfd47
Video Examples
Browse files- backend/examples.py +7 -5
- frontend/src/components/VideoGallery.tsx +116 -7
backend/examples.py
CHANGED
@@ -10,7 +10,7 @@ def group_files_by_index(file_paths, data_type="audio"):
|
|
10 |
if data_type == "audio":
|
11 |
pattern = r"audio_(\d+).(png|wav)"
|
12 |
elif data_type == "video":
|
13 |
-
pattern = r"video_(\d+).(png|
|
14 |
else:
|
15 |
pattern = r"img_(\d+).png"
|
16 |
# Dictionary to store the grouped files
|
@@ -110,11 +110,12 @@ def build_infos(abs_path: Path, datatype: str, dataset_name: str, db_key: str):
|
|
110 |
eval_results_path = abs_path + f"{dataset_name}_1k/examples_eval_results.json"
|
111 |
elif datatype == "video":
|
112 |
quality_metrics = ["psnr", "ssim", "lpips", "msssim", "vmaf"]
|
113 |
-
extensions = ["
|
114 |
datatype_abbr = "video"
|
115 |
eval_results_path = abs_path + f"{dataset_name}/examples_eval_results.json"
|
116 |
|
117 |
response = requests.get(eval_results_path)
|
|
|
118 |
if response.status_code == 200:
|
119 |
results_data = response.json()
|
120 |
else:
|
@@ -130,7 +131,7 @@ def build_infos(abs_path: Path, datatype: str, dataset_name: str, db_key: str):
|
|
130 |
]
|
131 |
|
132 |
file_patterns = generate_file_patterns(prefixes, extensions)
|
133 |
-
|
134 |
infos = {}
|
135 |
for model_name in dataset.keys():
|
136 |
model_infos = {}
|
@@ -192,7 +193,7 @@ def build_infos(abs_path: Path, datatype: str, dataset_name: str, db_key: str):
|
|
192 |
file_info["image_url"] = file.replace(".wav", ".png")
|
193 |
file_info["audio_url"] = file
|
194 |
elif datatype == "video":
|
195 |
-
file_info["image_url"] = file.replace(".
|
196 |
file_info["video_url"] = file
|
197 |
else:
|
198 |
file_info["image_url"] = file
|
@@ -263,7 +264,8 @@ def image_examples_tab(abs_path: Path):
|
|
263 |
|
264 |
|
265 |
def video_examples_tab(abs_path: Path):
|
266 |
-
dataset_name = "sav_val_full"
|
|
|
267 |
datatype = "video"
|
268 |
db_key = "sa-v_sav_val_videos"
|
269 |
|
|
|
10 |
if data_type == "audio":
|
11 |
pattern = r"audio_(\d+).(png|wav)"
|
12 |
elif data_type == "video":
|
13 |
+
pattern = r"video_(\d+).(png|mp4)"
|
14 |
else:
|
15 |
pattern = r"img_(\d+).png"
|
16 |
# Dictionary to store the grouped files
|
|
|
110 |
eval_results_path = abs_path + f"{dataset_name}_1k/examples_eval_results.json"
|
111 |
elif datatype == "video":
|
112 |
quality_metrics = ["psnr", "ssim", "lpips", "msssim", "vmaf"]
|
113 |
+
extensions = ["mp4"]
|
114 |
datatype_abbr = "video"
|
115 |
eval_results_path = abs_path + f"{dataset_name}/examples_eval_results.json"
|
116 |
|
117 |
response = requests.get(eval_results_path)
|
118 |
+
print(eval_results_path)
|
119 |
if response.status_code == 200:
|
120 |
results_data = response.json()
|
121 |
else:
|
|
|
131 |
]
|
132 |
|
133 |
file_patterns = generate_file_patterns(prefixes, extensions)
|
134 |
+
print(f"File patterns: {file_patterns}")
|
135 |
infos = {}
|
136 |
for model_name in dataset.keys():
|
137 |
model_infos = {}
|
|
|
193 |
file_info["image_url"] = file.replace(".wav", ".png")
|
194 |
file_info["audio_url"] = file
|
195 |
elif datatype == "video":
|
196 |
+
# file_info["image_url"] = file.replace(".mp4", ".png")
|
197 |
file_info["video_url"] = file
|
198 |
else:
|
199 |
file_info["image_url"] = file
|
|
|
264 |
|
265 |
|
266 |
def video_examples_tab(abs_path: Path):
|
267 |
+
# dataset_name = "sav_val_full"
|
268 |
+
dataset_name = "sav_val_full_v2"
|
269 |
datatype = "video"
|
270 |
db_key = "sa-v_sav_val_videos"
|
271 |
|
frontend/src/components/VideoGallery.tsx
CHANGED
@@ -4,6 +4,7 @@ import { groupByNameAndVariant } from './galleryUtils'
|
|
4 |
import ExampleVariantMetricsTable from './ExampleVariantMetricsTable'
|
5 |
import ExampleDetailsSection from './ExampleDetailsSection'
|
6 |
import ExampleVariantSelector from './ExampleVariantSelector'
|
|
|
7 |
|
8 |
interface GalleryProps {
|
9 |
selectedModel: string
|
@@ -23,6 +24,68 @@ const VideoGallery: React.FC<GalleryProps> = ({ selectedModel, selectedAttack, e
|
|
23 |
const variants = grouped[selectedVideo] || {}
|
24 |
const variantKeys = Object.keys(variants)
|
25 |
const [selectedVariant, setSelectedVariant] = React.useState(variantKeys[0] || '')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
React.useEffect(() => {
|
28 |
setSelectedVariant(variantKeys[0] || '')
|
@@ -72,14 +135,60 @@ const VideoGallery: React.FC<GalleryProps> = ({ selectedModel, selectedAttack, e
|
|
72 |
selectedVariant={selectedVariant}
|
73 |
setSelectedVariant={setSelectedVariant}
|
74 |
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
<div className="flex flex-col items-center gap-4">
|
76 |
-
{
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
)}
|
84 |
</div>
|
85 |
</ExampleDetailsSection>
|
|
|
4 |
import ExampleVariantMetricsTable from './ExampleVariantMetricsTable'
|
5 |
import ExampleDetailsSection from './ExampleDetailsSection'
|
6 |
import ExampleVariantSelector from './ExampleVariantSelector'
|
7 |
+
import ExampleVariantToggle from './ExampleVariantToggle'
|
8 |
|
9 |
interface GalleryProps {
|
10 |
selectedModel: string
|
|
|
24 |
const variants = grouped[selectedVideo] || {}
|
25 |
const variantKeys = Object.keys(variants)
|
26 |
const [selectedVariant, setSelectedVariant] = React.useState(variantKeys[0] || '')
|
27 |
+
const [toggleMode, setToggleMode] = React.useState<'wmd' | 'attacked'>('wmd')
|
28 |
+
// Add state for rewind seconds
|
29 |
+
const [rewindSeconds, setRewindSeconds] = React.useState(0.5)
|
30 |
+
// State for video scale
|
31 |
+
const [videoScale, setVideoScale] = React.useState(1)
|
32 |
+
|
33 |
+
// Playback time ref for syncing position
|
34 |
+
const playbackTimeRef = React.useRef(0)
|
35 |
+
// Refs for all video elements
|
36 |
+
const videoRefs = React.useMemo(() => {
|
37 |
+
const refs: Record<string, React.RefObject<HTMLVideoElement>> = {}
|
38 |
+
variantKeys.forEach((v) => {
|
39 |
+
refs[v] = React.createRef<HTMLVideoElement>()
|
40 |
+
})
|
41 |
+
return refs
|
42 |
+
}, [variantKeys.join(',')])
|
43 |
+
|
44 |
+
// Track which variant is currently playing
|
45 |
+
const [playingVariant, setPlayingVariant] = React.useState<string | null>(null)
|
46 |
+
|
47 |
+
// Play handler: pause all others, sync time
|
48 |
+
const handlePlay = (variant: string) => {
|
49 |
+
setPlayingVariant(variant)
|
50 |
+
variantKeys.forEach((v) => {
|
51 |
+
if (v !== variant && videoRefs[v]?.current) {
|
52 |
+
videoRefs[v]?.current?.pause()
|
53 |
+
}
|
54 |
+
})
|
55 |
+
}
|
56 |
+
// Pause handler
|
57 |
+
const handlePause = (variant: string) => {
|
58 |
+
if (playingVariant === variant) setPlayingVariant(null)
|
59 |
+
}
|
60 |
+
|
61 |
+
// When selectedVariant changes, sync playback position, rewind, and play state
|
62 |
+
React.useEffect(() => {
|
63 |
+
if (!selectedVariant) return
|
64 |
+
// Rewind playbackTimeRef by rewindSeconds, clamp to 0
|
65 |
+
playbackTimeRef.current = Math.max(0, playbackTimeRef.current - rewindSeconds)
|
66 |
+
// Set all videos to the new time, pause all except selected
|
67 |
+
variantKeys.forEach((v) => {
|
68 |
+
const ref = videoRefs[v]?.current
|
69 |
+
if (ref) {
|
70 |
+
ref.currentTime = playbackTimeRef.current
|
71 |
+
if (v !== selectedVariant) {
|
72 |
+
ref.pause()
|
73 |
+
}
|
74 |
+
}
|
75 |
+
})
|
76 |
+
// If a video was playing, continue playing the swapped variant
|
77 |
+
if (playingVariant && videoRefs[selectedVariant]?.current) {
|
78 |
+
videoRefs[selectedVariant].current.play()
|
79 |
+
}
|
80 |
+
}, [selectedVariant])
|
81 |
+
|
82 |
+
// When the selected video plays, update playbackTimeRef
|
83 |
+
const handleTimeUpdate = (variantKey: string) => {
|
84 |
+
const ref = videoRefs[variantKey]?.current
|
85 |
+
if (ref && variantKey === selectedVariant) {
|
86 |
+
playbackTimeRef.current = ref.currentTime
|
87 |
+
}
|
88 |
+
}
|
89 |
|
90 |
React.useEffect(() => {
|
91 |
setSelectedVariant(variantKeys[0] || '')
|
|
|
135 |
selectedVariant={selectedVariant}
|
136 |
setSelectedVariant={setSelectedVariant}
|
137 |
/>
|
138 |
+
<ExampleVariantToggle
|
139 |
+
toggleMode={toggleMode}
|
140 |
+
setToggleMode={setToggleMode}
|
141 |
+
type="button"
|
142 |
+
selectedVariant={selectedVariant}
|
143 |
+
setSelectedVariant={setSelectedVariant}
|
144 |
+
variantKeys={variantKeys}
|
145 |
+
/>
|
146 |
+
<div className="flex items-center gap-4 mt-2">
|
147 |
+
<label htmlFor="rewind-seconds" className="font-mono text-xs">Rewind Seconds:</label>
|
148 |
+
<input
|
149 |
+
id="rewind-seconds"
|
150 |
+
type="number"
|
151 |
+
min={0}
|
152 |
+
step={0.1}
|
153 |
+
value={rewindSeconds}
|
154 |
+
onChange={(e) => setRewindSeconds(Math.max(0, Number(e.target.value)))}
|
155 |
+
className="input input-bordered input-xs w-20"
|
156 |
+
placeholder="Seconds"
|
157 |
+
/>
|
158 |
+
<label htmlFor="video-scale" className="font-mono text-xs ml-4">Scale:</label>
|
159 |
+
<input
|
160 |
+
id="video-scale"
|
161 |
+
type="range"
|
162 |
+
min={0.3}
|
163 |
+
max={1}
|
164 |
+
step={0.01}
|
165 |
+
value={videoScale}
|
166 |
+
onChange={e => setVideoScale(Number(e.target.value))}
|
167 |
+
className="range range-xs w-40"
|
168 |
+
style={{ verticalAlign: 'middle' }}
|
169 |
+
/>
|
170 |
+
<span className="ml-2 font-mono text-xs">{(videoScale * 100).toFixed(0)}%</span>
|
171 |
+
</div>
|
172 |
<div className="flex flex-col items-center gap-4">
|
173 |
+
{variantKeys.map((variantKey) =>
|
174 |
+
variants[variantKey].video_url ? (
|
175 |
+
<video
|
176 |
+
key={variantKey}
|
177 |
+
ref={videoRefs[variantKey]}
|
178 |
+
controls
|
179 |
+
src={variants[variantKey].video_url}
|
180 |
+
className="example-video"
|
181 |
+
style={{
|
182 |
+
width: `${videoScale * 100}%`,
|
183 |
+
height: 'auto',
|
184 |
+
display: selectedVariant === variantKey ? 'block' : 'none',
|
185 |
+
maxWidth: '100%',
|
186 |
+
}}
|
187 |
+
onTimeUpdate={() => handleTimeUpdate(variantKey)}
|
188 |
+
onPlay={() => handlePlay(variantKey)}
|
189 |
+
onPause={() => handlePause(variantKey)}
|
190 |
+
/>
|
191 |
+
) : null
|
192 |
)}
|
193 |
</div>
|
194 |
</ExampleDetailsSection>
|