Spaces:
Build error
Build error
Commit
•
b84093c
1
Parent(s):
7eb3b9c
ready for the update
Browse files- database.json +88 -1
- scripts/README.md +9 -0
- scripts/init.sh +26 -4
- scripts/interpolate.sh +48 -0
- scripts/stream3.sh +9 -0
- scripts/stream4.sh +9 -0
- scripts/video3.sh +27 -0
- scripts/video4.sh +26 -0
- src/index.mts +4 -0
- src/interpolate/TODO_USE_ME.mts +27 -0
- src/interpolateVideo.mts +55 -17
- src/postprod/interpolate.mts +7 -21
- src/postprod/interpolateVideoForScript.mts +53 -0
- test.sh +2 -0
database.json
CHANGED
@@ -2,6 +2,93 @@
|
|
2 |
"version": 1,
|
3 |
"startAtShotId": "",
|
4 |
"sequences": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
{
|
6 |
"sequenceId": "3b7fb664-f50a-4e2d-b63b-e1fedb22e501",
|
7 |
"skip": false,
|
@@ -382,7 +469,7 @@
|
|
382 |
},
|
383 |
{
|
384 |
"sequenceId": "a8ea6aac-c857-436c-877a-28ebe3420209",
|
385 |
-
"skip":
|
386 |
"lastGenerationAt": "",
|
387 |
"videoPrompt": "a photorealistic movie, experimental horror movie showing creepy places, pool of blood, a creepy mansion, a woman in white near the road in the forest, mist and foggy woods, a cemetery, a creepy animal or deer-like monster creeping around. The movie is esoteric, there are some dreamy places.",
|
388 |
"audioPrompt": "ambient electronic music from the 50s kraftwerk inspiration",
|
|
|
2 |
"version": 1,
|
3 |
"startAtShotId": "",
|
4 |
"sequences": [
|
5 |
+
{
|
6 |
+
"sequenceId": "da6329e1-c863-45e0-aa18-5161cf5eeacd",
|
7 |
+
"skip": false,
|
8 |
+
"lastGenerationAt": "",
|
9 |
+
"videoPrompt": "a photorealistic of a space opera movie",
|
10 |
+
"audioPrompt": "intense and fast-paced electronic and orchestra music for a space opera with synthetisers, electronic drum machine",
|
11 |
+
"tags": [
|
12 |
+
"trailer",
|
13 |
+
"comedy",
|
14 |
+
"action",
|
15 |
+
"adventure",
|
16 |
+
"science-fiction"
|
17 |
+
],
|
18 |
+
"channel": "main",
|
19 |
+
"shots": [
|
20 |
+
{
|
21 |
+
"shotId": "63462eef-7fa0-46b6-855a-c70dcebfb414",
|
22 |
+
"index": 0,
|
23 |
+
"lastGenerationAt": "",
|
24 |
+
"videoPrompt": "Photorealistic movie footage of a detailed NASA-inspired, pyramid-shaped spaceship soaring towards a strange planet laden with a colossal castle, glinting enchantingly under the golden hour sunlight, viewed from the perspective of an ultra wide-angle cinema camera, a spectacular, cinematic, photorealistic, movie quality shot.",
|
25 |
+
"audioPrompt": ""
|
26 |
+
},
|
27 |
+
{
|
28 |
+
"shotId": "5d4b89f0-ba68-499c-be41-61ca447720c7",
|
29 |
+
"index": 1,
|
30 |
+
"lastGenerationAt": "",
|
31 |
+
"videoPrompt": "Photorealistic film of a raccoon pilot in an expansive spaceship cockpit, wearing an airman's leather jacket and goggles, illuminated by ambient lighting from the spacecraft's controls, shot with high details, digitally remastered, award-winning.",
|
32 |
+
"audioPrompt": ""
|
33 |
+
},
|
34 |
+
{
|
35 |
+
"shotId": "c1d2e49d-abb2-42c8-8ed7-d9eadcbfc152",
|
36 |
+
"index": 2,
|
37 |
+
"lastGenerationAt": "",
|
38 |
+
"videoPrompt": "Ultra-wide angle photorealistic shot of huge, freeze-breathing dragons, their scales glistening unnervingly under the sunlight, amid massive octopus creatures upturning alien houses, shot with a mix of ambient lighting and backlighting in superb photorealistic, cinematic, movie quality.",
|
39 |
+
"audioPrompt": ""
|
40 |
+
},
|
41 |
+
{
|
42 |
+
"shotId": "268fdad6-07db-426b-812d-dc03c30ffe49",
|
43 |
+
"index": 3,
|
44 |
+
"lastGenerationAt": "",
|
45 |
+
"videoPrompt": "Captivating photorealistic footage of our raccoon pilot passionately manipulating the spaceship's controls amidst the tumultuous situation outdoors, captured in soft lighting from a Canon EOS cinema-grade camera, showcasing splendid, award-winning composition and detail",
|
46 |
+
"audioPrompt": ""
|
47 |
+
},
|
48 |
+
{
|
49 |
+
"shotId": "c431acda-a572-4fc0-ba4a-179d98219f48",
|
50 |
+
"index": 4,
|
51 |
+
"lastGenerationAt": "",
|
52 |
+
"videoPrompt": "Space opera drama unfolding in a photorealistic footage of phenomenal, giant icy dragons sweeping over expansive, medieval-style castle, casting long, dramatic shadows under the slowly setting sun, captured in sublime movie quality.",
|
53 |
+
"audioPrompt": ""
|
54 |
+
},
|
55 |
+
{
|
56 |
+
"shotId": "62971863-1448-4044-a50c-242af4de953e",
|
57 |
+
"index": 5,
|
58 |
+
"lastGenerationAt": "",
|
59 |
+
"videoPrompt": "Photorealistic film shot of the ecstatic raccoon pilot reacting to the chaos outside, speeding towards the planet in his spaceship, the merriment in his beady eyes reflected in the surreal and breathtaking high-quality, movie lighting, captured with stunning detail.",
|
60 |
+
"audioPrompt": ""
|
61 |
+
},
|
62 |
+
{
|
63 |
+
"shotId": "4aa96204-c78f-47b3-b6ca-a9e1faf5b7a0",
|
64 |
+
"index": 6,
|
65 |
+
"lastGenerationAt": "",
|
66 |
+
"videoPrompt": "Highly detailed, photorealistic footage of ominous eight-legged giant octopuses briskly roaming a wild, otherworldly landscape, crushing alien houses in their path, as our raccoon hero watches in awe, their movement fluid like in an epic space opera movie.",
|
67 |
+
"audioPrompt": ""
|
68 |
+
},
|
69 |
+
{
|
70 |
+
"shotId": "bd89e7ce-01e9-449a-b468-550e43956e77",
|
71 |
+
"index": 7,
|
72 |
+
"lastGenerationAt": "",
|
73 |
+
"videoPrompt": "Photorealistic movie shot of intricate details of the spaceship cockpit with the dedicated and absorbed raccoon pilot urgently plotting a course for escape, shadows and lights from the control panels play on his fur, showcasing stunning detail.",
|
74 |
+
"audioPrompt": ""
|
75 |
+
},
|
76 |
+
{
|
77 |
+
"shotId": "4eba4b78-1d2f-4795-82b0-f56e6004e8fe",
|
78 |
+
"index": 8,
|
79 |
+
"lastGenerationAt": "",
|
80 |
+
"videoPrompt": "Ultra-wide angle, photorealistic shot of the planet's dawn, with the iridescent glow revealing the frozen wreckage caused by the dragons, taking on an ethereal quality amidst the chaos, shot in a cinematic manner, maintaining high details to procure an award-winning shot.",
|
81 |
+
"audioPrompt": ""
|
82 |
+
},
|
83 |
+
{
|
84 |
+
"shotId": "c3f5a185-cace-46bf-a74c-27f7114e75ce",
|
85 |
+
"index": 9,
|
86 |
+
"lastGenerationAt": "",
|
87 |
+
"videoPrompt": "Cinematic, photorealistic video of our raccoon hero in his spaceship, glancing back at the strange planet, a mix of pride and melancholy in his gaze as his spaceship disappears into the starry void, lighting from the control panel casting a soft glow on his figure, award-winning filmography.",
|
88 |
+
"audioPrompt": ""
|
89 |
+
}
|
90 |
+
]
|
91 |
+
},
|
92 |
{
|
93 |
"sequenceId": "3b7fb664-f50a-4e2d-b63b-e1fedb22e501",
|
94 |
"skip": false,
|
|
|
469 |
},
|
470 |
{
|
471 |
"sequenceId": "a8ea6aac-c857-436c-877a-28ebe3420209",
|
472 |
+
"skip": true,
|
473 |
"lastGenerationAt": "",
|
474 |
"videoPrompt": "a photorealistic movie, experimental horror movie showing creepy places, pool of blood, a creepy mansion, a woman in white near the road in the forest, mist and foggy woods, a cemetery, a creepy animal or deer-like monster creeping around. The movie is esoteric, there are some dreamy places.",
|
475 |
"audioPrompt": "ambient electronic music from the 50s kraftwerk inspiration",
|
scripts/README.md
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
## Scripts
|
4 |
+
|
5 |
+
### interpolate.sh
|
6 |
+
|
7 |
+
This is a script meant to be run on an existing video database.
|
8 |
+
This can help making quick trials of interpolation algorithms,
|
9 |
+
without modifying the video creating pipeline.
|
scripts/init.sh
CHANGED
@@ -5,10 +5,6 @@ echo "creating the storage folders for channel 1.."
|
|
5 |
mkdir -p $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_1
|
6 |
mkdir -p $WEBTV_AUDIO_STORAGE_PATH_CHANNEL_1
|
7 |
|
8 |
-
bash scripts/download_fresh_music.sh
|
9 |
-
|
10 |
-
bash scripts/censorship.sh
|
11 |
-
|
12 |
echo "creating the playlists for channel 1.."
|
13 |
echo "ffconcat version 1.0" > channel_1_video.txt
|
14 |
echo "ffconcat version 1.0" > channel_1_audio.txt
|
@@ -21,3 +17,29 @@ mkdir -p $WEBTV_AUDIO_STORAGE_PATH_CHANNEL_2
|
|
21 |
echo "creating the playlists for channel 2.."
|
22 |
echo "ffconcat version 1.0" > channel_2_video.txt
|
23 |
echo "ffconcat version 1.0" > channel_2_video.txt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
mkdir -p $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_1
|
6 |
mkdir -p $WEBTV_AUDIO_STORAGE_PATH_CHANNEL_1
|
7 |
|
|
|
|
|
|
|
|
|
8 |
echo "creating the playlists for channel 1.."
|
9 |
echo "ffconcat version 1.0" > channel_1_video.txt
|
10 |
echo "ffconcat version 1.0" > channel_1_audio.txt
|
|
|
17 |
echo "creating the playlists for channel 2.."
|
18 |
echo "ffconcat version 1.0" > channel_2_video.txt
|
19 |
echo "ffconcat version 1.0" > channel_2_video.txt
|
20 |
+
|
21 |
+
|
22 |
+
# ------------- CHANNEL 3 --------------
|
23 |
+
echo "creating the storage folders for channel 3.."
|
24 |
+
mkdir -p $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_3
|
25 |
+
mkdir -p $WEBTV_AUDIO_STORAGE_PATH_CHANNEL_3
|
26 |
+
|
27 |
+
echo "creating the playlists for channel 3.."
|
28 |
+
echo "ffconcat version 1.0" > channel_3_video.txt
|
29 |
+
echo "ffconcat version 1.0" > channel_3_video.txt
|
30 |
+
|
31 |
+
|
32 |
+
# ------------- CHANNEL 4 --------------
|
33 |
+
echo "creating the storage folders for channel 4.."
|
34 |
+
mkdir -p $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_4
|
35 |
+
mkdir -p $WEBTV_AUDIO_STORAGE_PATH_CHANNEL_4
|
36 |
+
|
37 |
+
echo "creating the playlists for channel 4.."
|
38 |
+
echo "ffconcat version 1.0" > channel_4_video.txt
|
39 |
+
echo "ffconcat version 1.0" > channel_4_video.txt
|
40 |
+
|
41 |
+
# ------------ UPDATE MUSIC ------------
|
42 |
+
bash scripts/download_fresh_music.sh
|
43 |
+
|
44 |
+
# ---------- CONTENT ALIGNMENT ---------
|
45 |
+
bash scripts/censorship.sh
|
scripts/interpolate.sh
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Make sure to provide your directories paths
|
4 |
+
INPUT_DIR=$WEBTV_VIDEO_STORAGE_PATH_CHANNEL_2
|
5 |
+
OUTPUT_DIR=$WEBTV_VIDEO_STORAGE_PATH_CHANNEL_3
|
6 |
+
TEMP_DIR=$(mktemp -d)
|
7 |
+
|
8 |
+
# Loop through all .mp4 files in input directory
|
9 |
+
for FILE_PATH in $INPUT_DIR*.mp4; do
|
10 |
+
# get the base file name
|
11 |
+
FILE_NAME=$(basename "$FILE_PATH")
|
12 |
+
|
13 |
+
# Create a temp file path
|
14 |
+
TEMP_FILE_PATH=$TEMP_DIR"/"$FILE_NAME
|
15 |
+
|
16 |
+
# Check if file does not exist in output directory
|
17 |
+
if [ ! -f "$OUTPUT_DIR$FILE_NAME" ]; then
|
18 |
+
echo "Processing $FILE_NAME, output will be saved in $OUTPUT_DIR$FILE_NAME"
|
19 |
+
|
20 |
+
# Run your node command
|
21 |
+
if ! npm run postprod:interpolate "$FILE_PATH" "$TEMP_FILE_PATH"
|
22 |
+
then
|
23 |
+
# The first attempt has failed, retrying
|
24 |
+
echo "Attempt 1 failed for $FILE_NAME, retrying..."
|
25 |
+
|
26 |
+
if ! npm run postprod:interpolate "$FILE_PATH" "$TEMP_FILE_PATH"
|
27 |
+
then
|
28 |
+
# Both attempts have failed, skipping the file
|
29 |
+
echo "Both attempts failed for $FILE_NAME, skipping the file..."
|
30 |
+
continue
|
31 |
+
fi
|
32 |
+
fi
|
33 |
+
|
34 |
+
# Running ffmpeg to resize and apply unsharp mask
|
35 |
+
# Also we speed things up, and re-add the noise
|
36 |
+
if ! ffmpeg -hide_banner -v fatal -nostats -loglevel 0 -i "$TEMP_FILE_PATH" -vf "setpts=0.35*PTS,scale=-1:576:lanczos,unsharp=5:5:0.2:5:5:0.2,noise=c0s=10:c0f=t+u" -r 24 "$OUTPUT_DIR$FILE_NAME"
|
37 |
+
then
|
38 |
+
# ffmpeg command failed
|
39 |
+
echo "ffmpeg command failed for $FILE_NAME, skipping the file..."
|
40 |
+
fi
|
41 |
+
|
42 |
+
else
|
43 |
+
echo "File $FILE_NAME already exists in the output directory, skipping."
|
44 |
+
fi
|
45 |
+
done
|
46 |
+
|
47 |
+
# Remove temp folder
|
48 |
+
rm -r "$TEMP_DIR"
|
scripts/stream3.sh
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
COUNT=0
|
4 |
+
|
5 |
+
echo "Starting FFMPEG live stream for channel 3"
|
6 |
+
while true; do
|
7 |
+
# Note: for now we also use channel 1 for audio!
|
8 |
+
ffmpeg -y -nostdin -re -f concat -safe 0 -i channel_3_video.txt -stream_loop -1 -safe 0 -i channel_1_audio.txt -loglevel error -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -ar 44100 -shortest -f flv rtmp://localhost/live/smooth
|
9 |
+
done
|
scripts/stream4.sh
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
COUNT=0
|
4 |
+
|
5 |
+
echo "Starting FFMPEG live stream for channel 4"
|
6 |
+
while true; do
|
7 |
+
# Note: for now we also use channel 1 for audio!
|
8 |
+
ffmpeg -y -nostdin -re -f concat -safe 0 -i channel_4_video.txt -stream_loop -1 -safe 0 -i channel_1_audio.txt -loglevel error -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -ar 44100 -shortest -f flv rtmp://localhost/live/interactive
|
9 |
+
done
|
scripts/video3.sh
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
echo "Starting the video collection stream for channel 3.."
|
4 |
+
echo "listing files in $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_3*.mp4"
|
5 |
+
current_count=0
|
6 |
+
|
7 |
+
while true; do
|
8 |
+
new_count=$(ls $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_3*.mp4 2> /dev/null | wc -l)
|
9 |
+
|
10 |
+
if [ $new_count -ne $current_count ]; then
|
11 |
+
echo "there are $new_count videos files for channel 3"
|
12 |
+
|
13 |
+
echo "Updating playliss for channel 3.."
|
14 |
+
current_count=$new_count
|
15 |
+
files=($WEBTV_VIDEO_STORAGE_PATH_CHANNEL_2*.mp4)
|
16 |
+
|
17 |
+
echo "ffconcat version 1.0" > channel_3_video_tmp.txt
|
18 |
+
for (( i=0; i<${#files[@]}; i++ )); do
|
19 |
+
echo "file '${files[$i]}'" >> channel_3_video_tmp.txt
|
20 |
+
done
|
21 |
+
mv channel_3_video_tmp.txt channel_3_video.txt
|
22 |
+
fi
|
23 |
+
|
24 |
+
# the new playlist will only be updated after the current playlist ended
|
25 |
+
# so there is no emergency here
|
26 |
+
sleep 60
|
27 |
+
done
|
scripts/video4.sh
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
echo "Starting the video collection stream for channel 4.."
|
4 |
+
echo "listing files in $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_4*.mp4"
|
5 |
+
current_count=0
|
6 |
+
|
7 |
+
while true; do
|
8 |
+
new_count=$(ls $WEBTV_VIDEO_STORAGE_PATH_CHANNEL_4*.mp4 2> /dev/null | wc -l)
|
9 |
+
|
10 |
+
if [ $new_count -ne $current_count ]; then
|
11 |
+
echo "there are $new_count videos files for channel 4"
|
12 |
+
|
13 |
+
echo "Updating playliss for channel 4.."
|
14 |
+
current_count=$new_count
|
15 |
+
files=($WEBTV_VIDEO_STORAGE_PATH_CHANNEL_4*.mp4)
|
16 |
+
|
17 |
+
echo "ffconcat version 1.0" > channel_4_video_tmp.txt
|
18 |
+
for (( i=0; i<${#files[@]}; i++ )); do
|
19 |
+
echo "file '${files[$i]}'" >> channel_4_video_tmp.txt
|
20 |
+
done
|
21 |
+
mv channel_4_video_tmp.txt channel_4_video.txt
|
22 |
+
fi
|
23 |
+
|
24 |
+
# channel 4 is an interactive channel, so we have tighter delays
|
25 |
+
sleep 20
|
26 |
+
done
|
src/index.mts
CHANGED
@@ -8,6 +8,7 @@ import { callZeroscope } from './callZeroscope.mts'
|
|
8 |
import { downloadVideo } from './downloadVideo.mts'
|
9 |
import { getDatabase } from './getDatabase.mts'
|
10 |
import { callMusicgen } from './callMusicgen.mts'
|
|
|
11 |
|
12 |
let hasReachedStartingPoint = false
|
13 |
|
@@ -125,6 +126,9 @@ ${sequence.videoPrompt}
|
|
125 |
await upscaleVideo(shotFileName, shot.videoPrompt)
|
126 |
}
|
127 |
|
|
|
|
|
|
|
128 |
console.log('- enhancing shot..')
|
129 |
await enhanceVideo(shotFileName)
|
130 |
|
|
|
8 |
import { downloadVideo } from './downloadVideo.mts'
|
9 |
import { getDatabase } from './getDatabase.mts'
|
10 |
import { callMusicgen } from './callMusicgen.mts'
|
11 |
+
import { interpolateVideo } from './interpolateVideo.mts'
|
12 |
|
13 |
let hasReachedStartingPoint = false
|
14 |
|
|
|
126 |
await upscaleVideo(shotFileName, shot.videoPrompt)
|
127 |
}
|
128 |
|
129 |
+
console.log('- enhancing shot..')
|
130 |
+
// await interpolateVideo(shotFileName)
|
131 |
+
|
132 |
console.log('- enhancing shot..')
|
133 |
await enhanceVideo(shotFileName)
|
134 |
|
src/interpolate/TODO_USE_ME.mts
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { promises as fs } from "node:fs"
|
2 |
+
import path from "node:path"
|
3 |
+
|
4 |
+
import { client } from "@gradio/client"
|
5 |
+
import tmpDir from "temp-dir"
|
6 |
+
|
7 |
+
const spaceUrl = "https://jbilcke-hf-video-frame-interpolation.hf.space"
|
8 |
+
|
9 |
+
export const interpolateVideo = (fileName: string) {
|
10 |
+
|
11 |
+
const filePath = path.join(tmpDir, fileName)
|
12 |
+
|
13 |
+
const app = await client(spaceUrl)
|
14 |
+
|
15 |
+
const video = await fs.readFile(filePath)
|
16 |
+
|
17 |
+
const result = await app.predict(1, [
|
18 |
+
video.toString('base64'), // blob in 'parameter_5' Video component
|
19 |
+
1, // number (numeric value between 1 and 4) in 'Interpolation Steps' Slider component
|
20 |
+
"24", // string in 'FPS output' Radio component
|
21 |
+
])
|
22 |
+
|
23 |
+
const data = (result as any).data
|
24 |
+
|
25 |
+
console.log(data)
|
26 |
+
|
27 |
+
}
|
src/interpolateVideo.mts
CHANGED
@@ -1,27 +1,65 @@
|
|
1 |
-
import
|
2 |
-
import
|
3 |
|
4 |
-
import
|
5 |
-
import
|
|
|
6 |
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
-
|
10 |
|
11 |
-
const
|
12 |
-
|
13 |
-
const app = await client(spaceUrl)
|
14 |
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
-
const data = (result as any).data
|
24 |
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
|
|
27 |
}
|
|
|
1 |
+
import path from 'node:path'
|
2 |
+
import fs from 'node:fs'
|
3 |
|
4 |
+
import tmpDir from 'temp-dir'
|
5 |
+
import puppeteer from 'puppeteer'
|
6 |
+
import { downloadVideo } from './downloadVideo.mts'
|
7 |
|
8 |
+
// TODO we should use an inference endpoint instead
|
9 |
+
export async function interpolateVideo(fileName: string) {
|
10 |
+
|
11 |
+
const browser = await puppeteer.launch({
|
12 |
+
// headless: true,
|
13 |
+
protocolTimeout: 300000,
|
14 |
+
})
|
15 |
|
16 |
+
const spaceUrl = process.env.WEBTV_INTERPOLATION_SPACE_URL
|
17 |
|
18 |
+
const page = await browser.newPage()
|
|
|
|
|
19 |
|
20 |
+
await page.goto(spaceUrl, {
|
21 |
+
waitUntil: 'networkidle2',
|
22 |
+
})
|
23 |
+
|
24 |
+
const inputFilePath = path.join(tmpDir, fileName)
|
25 |
+
// console.log(`local file to upscale: ${inputFilePath}`)
|
26 |
|
27 |
+
await new Promise(r => setTimeout(r, 3000))
|
28 |
+
|
29 |
+
const fileField = await page.$('input[type=file]')
|
30 |
+
|
31 |
+
// console.log(`uploading file..`)
|
32 |
+
await fileField.uploadFile(inputFilePath)
|
33 |
+
|
34 |
+
// console.log('looking for the button to submit')
|
35 |
+
const submitButton = await page.$('button.lg')
|
36 |
+
|
37 |
+
// console.log('clicking on the button')
|
38 |
+
await submitButton.click()
|
39 |
|
|
|
40 |
|
41 |
+
await page.waitForSelector('a[download="interpolated_result.mp4"]', {
|
42 |
+
timeout: 300000, // need to be large enough in case someone else attemps to use our space
|
43 |
+
})
|
44 |
+
|
45 |
+
const interpolatedFileUrl = await page.$$eval('a[download="interpolated_result.mp4"]', el => el.map(x => x.getAttribute("href"))[0])
|
46 |
+
|
47 |
+
const tmpFileName = `${fileName}_xl`
|
48 |
+
|
49 |
+
// console.log('downloading file from space..')
|
50 |
+
console.log(`- downloading ${fileName} from ${interpolatedFileUrl}`)
|
51 |
+
|
52 |
+
await downloadVideo(interpolatedFileUrl, tmpFileName)
|
53 |
+
|
54 |
+
const tmpFilePath = path.join(tmpDir, tmpFileName)
|
55 |
+
const filePath = path.join(tmpDir, fileName)
|
56 |
+
|
57 |
+
await fs.promises.copyFile(tmpFilePath, filePath)
|
58 |
+
try {
|
59 |
+
await fs.promises.unlink(tmpFilePath)
|
60 |
+
} catch (err) {
|
61 |
+
console.log('failed to cleanup (no big deal..)')
|
62 |
+
}
|
63 |
|
64 |
+
return fileName
|
65 |
}
|
src/postprod/interpolate.mts
CHANGED
@@ -1,26 +1,12 @@
|
|
1 |
-
import {
|
2 |
-
import { client } from "@gradio/client"
|
3 |
|
4 |
// to test this file:
|
5 |
-
// npm run postprod:interpolate sandbox/video/1688471841394.mp4
|
6 |
|
7 |
-
const
|
8 |
-
const
|
9 |
|
10 |
-
console.log('
|
11 |
-
|
12 |
-
|
13 |
-
const b64 = vid.toString('base64')
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
const app = await client(spaceUrl)
|
18 |
-
|
19 |
-
/*
|
20 |
-
const result = await app.predict(1, [
|
21 |
-
exampleVideo, // blob in 'parameter_5' Video component
|
22 |
-
1, // number (numeric value between 1 and 4) in 'Interpolation Steps' Slider component
|
23 |
-
"8", // string in 'FPS output' Radio component
|
24 |
-
]);
|
25 |
-
console.log(result?.data)
|
26 |
-
*/
|
|
|
1 |
+
import { interpolateVideo } from "./interpolateVideoForScript.mts"
|
|
|
2 |
|
3 |
// to test this file:
|
4 |
+
// npm run postprod:interpolate sandbox/video/1688471841394.mp4 sandbox/video/output.mp4
|
5 |
|
6 |
+
const inputFilePath = process.argv[2]
|
7 |
+
const outputFilePath = process.argv[3]
|
8 |
|
9 |
+
console.log('input file path:', inputFilePath)
|
10 |
+
console.log('output file path:', outputFilePath)
|
|
|
|
|
11 |
|
12 |
+
await interpolateVideo(inputFilePath, outputFilePath)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/postprod/interpolateVideoForScript.mts
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import fs from 'node:fs'
|
2 |
+
|
3 |
+
import puppeteer from 'puppeteer'
|
4 |
+
|
5 |
+
// TODO we should use an inference endpoint instead
|
6 |
+
export async function interpolateVideo(inputFilePath: string, outputFilePath: string) {
|
7 |
+
|
8 |
+
const browser = await puppeteer.launch({
|
9 |
+
headless: true,
|
10 |
+
protocolTimeout: 400000,
|
11 |
+
})
|
12 |
+
|
13 |
+
const spaceUrl = process.env.WEBTV_INTERPOLATION_SPACE_URL
|
14 |
+
|
15 |
+
const page = await browser.newPage()
|
16 |
+
await page.goto(spaceUrl, { waitUntil: 'networkidle2' })
|
17 |
+
|
18 |
+
await new Promise(r => setTimeout(r, 3000))
|
19 |
+
|
20 |
+
const fileField = await page.$('input[type=file]')
|
21 |
+
|
22 |
+
// console.log(`uploading file..`)
|
23 |
+
await fileField.uploadFile(inputFilePath)
|
24 |
+
|
25 |
+
// console.log('looking for the button to submit')
|
26 |
+
const submitButton = await page.$('button.lg')
|
27 |
+
|
28 |
+
// console.log('clicking on the button')
|
29 |
+
await submitButton.click()
|
30 |
+
|
31 |
+
await page.waitForSelector('a[download="interpolated_result.mp4"]', {
|
32 |
+
timeout: 400000, // need to be large enough in case someone else attemps to use our space
|
33 |
+
})
|
34 |
+
|
35 |
+
const interpolatedFileUrl = await page.$$eval('a[download="interpolated_result.mp4"]', el => el.map(x => x.getAttribute("href"))[0])
|
36 |
+
|
37 |
+
// console.log('downloading file from space..')
|
38 |
+
console.log(`- downloading from ${interpolatedFileUrl}`)
|
39 |
+
|
40 |
+
|
41 |
+
// download the video
|
42 |
+
const response = await fetch(interpolatedFileUrl)
|
43 |
+
// write it to the disk
|
44 |
+
const arrayBuffer = await response.arrayBuffer()
|
45 |
+
|
46 |
+
await fs.promises.writeFile(
|
47 |
+
outputFilePath,
|
48 |
+
Buffer.from(arrayBuffer)
|
49 |
+
)
|
50 |
+
console.log('success! wrote to:', outputFilePath)
|
51 |
+
|
52 |
+
process.exit()
|
53 |
+
}
|
test.sh
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
echo "$FOO$BAR"
|
2 |
+
|