├── LICENSE ├── README.md ├── python ├── spin-zoom │ ├── README.md │ ├── requirements.txt │ ├── spin-zoom.gif │ └── spin-zoom.py └── vid2vid │ ├── README.md │ ├── example.gif │ ├── requirements.txt │ └── vid2vid.py └── web └── plain-js ├── PlainJS.html ├── README.md └── screenshot.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 compute(r)ender 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tutorials 2 | Examples using the [computerender](https://computerender.com) API 3 | 4 | ## Python 5 | 6 | - [vid2vid](python/vid2vid/) 7 | 8 | 9 | - [spin-zoom](python/spin-zoom/) 10 | 11 | 12 | ## Web 13 | 14 | - [plain-js](web/plain-js/) 15 | 16 | -------------------------------------------------------------------------------- /python/spin-zoom/README.md: -------------------------------------------------------------------------------- 1 | # vid2vid 2 | 3 | Spinning zoom effect using stable diffusion via [computerender](https://computerender.com). 4 | 5 | 6 | 7 | ## 1. Setup 8 | You can install the python dependencies by running: 9 | 10 | ```bash 11 | pip install -r requirements.txt 12 | ``` 13 | 14 | To install install ffmpeg: 15 | Linux 16 | ```bash 17 | apt install ffmpeg 18 | ``` 19 | Macos: 20 | ```bash 21 | brew install ffmpeg 22 | ``` 23 | Windows: 24 | https://ffmpeg.org/download.html 25 | 26 | ## 2. API Key 27 | You can get an API key by making an account at https://computerender.com/account.html 28 | To make your key visible to the python client, you can add it as an environment variable: 29 | ```bash 30 | export CR_KEY=sk_your_key_here 31 | ``` 32 | Or alternatively provide it when initializing the client in the python script: 33 | ```python 34 | cr = Computerender("sk_your_key_here") 35 | ``` 36 | 37 | ## 3. Running the script 38 | It is a good idea to first create a short, trimmed version of your video that's just a few frames. 39 | This will be helpful for tuning parameters to get the right amount of modification to your video. 40 | Most importantly, the "strength" parameter will determine how much influence the effect has. 41 | The angle and zoom parameters control the speed of the zooming effect. 42 | 43 | Run the script: 44 | ```bash 45 | python spin-zoom.py 46 | ``` 47 | 48 | ## 4. Post processing 49 | To produce the final output, the video was imported into adobe premiere and slowed using "optical flow" as the frame interpolation. It may be possible to achieve the same effect using opencv, but that is not covered in this tutorial. 50 | -------------------------------------------------------------------------------- /python/spin-zoom/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | Pillow 3 | tqdm 4 | mediapy 5 | computerender -------------------------------------------------------------------------------- /python/spin-zoom/spin-zoom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/computerender/tutorials/d65208541f9ac59ea3ff321d10928b0b72ad849a/python/spin-zoom/spin-zoom.gif -------------------------------------------------------------------------------- /python/spin-zoom/spin-zoom.py: -------------------------------------------------------------------------------- 1 | import math 2 | from io import BytesIO 3 | import asyncio 4 | from computerender import Computerender 5 | from tqdm import tqdm 6 | from PIL import Image 7 | import numpy as np 8 | from mediapy import VideoWriter 9 | 10 | input_file = "IMG_4839.jpeg" # <-- Starting image 11 | output_file = "sd-zoom-output.mp4" 12 | prompt = "beautiful lush forest, national geographic" 13 | frames = 100 # Length of video 14 | strength = 0.4 # How strong the styling effect should be (range 0.1-1.0) 15 | scale_speed = 0.98 # How fast to zoom 16 | angle_speed = 0.9 * 2 * math.pi / 360 # How fast to rotate 17 | iterations = 60 18 | guidance = 11.0 19 | output_res = (512, 512) 20 | out_r = (output_res[1], output_res[0]) 21 | parallel_jobs = 4 22 | 23 | # using the cropping method from here: 24 | # https://note.nkmk.me/en/python-pillow-square-circle-thumbnail/ 25 | def crop_center(pil_img, crop_width, crop_height): 26 | img_width, img_height = pil_img.size 27 | return pil_img.crop(((img_width - crop_width) // 2, 28 | (img_height - crop_height) // 2, 29 | (img_width + crop_width) // 2, 30 | (img_height + crop_height) // 2)) 31 | 32 | def crop_max_square(pil_img): 33 | return crop_center(pil_img, min(pil_img.size), min(pil_img.size)) 34 | 35 | # PIL doesn't have a great way for building 36 | # affine transformations so we're doing it manually 37 | def create_transform(angle, scale, dimensions): 38 | # center of image 39 | x = dimensions[0] // 2 40 | y = dimensions[1] // 2 41 | 42 | # translation matrix to center of image 43 | trans_a = np.array([[1, 0, x], 44 | [0, 1, y], 45 | [0, 0, 1]]) 46 | # rotation matrix 47 | rot = np.array([[math.cos(angle), math.sin(angle), 0], 48 | [-math.sin(angle), math.cos(angle), 0], 49 | [0, 0, 1]]) 50 | # scale matrix 51 | scale = np.array([[scale_speed, 0, 0], 52 | [0, scale_speed, 0], 53 | [0, 0, 1]]) 54 | # translate back to original position 55 | trans_b = np.array([[1, 0, -x], 56 | [0, 1, -y], 57 | [0, 0, 1]]) 58 | # compose transformations into a single matrix 59 | return trans_a @ rot @ scale @ trans_b 60 | 61 | cr = Computerender() 62 | 63 | async def img2img(img, strength_mul, seed): 64 | img_bytes = BytesIO() 65 | img.save(img_bytes, format="jpeg") 66 | img_out = await cr.generate( 67 | prompt, iterations=iterations, seed=seed, strength=strength*strength_mul, 68 | guidance=guidance, img=img_bytes.getvalue() 69 | ) 70 | return Image.open(BytesIO(img_out)) 71 | 72 | async def main(): 73 | 74 | # load base image 75 | cur_img = crop_max_square( 76 | Image.open(input_file) 77 | ).resize(output_res, Image.Resampling.NEAREST) 78 | 79 | with VideoWriter(output_file, shape=output_res, fps=30) as w: 80 | 81 | w.add_image(np.array(cur_img)) 82 | 83 | # for each frame 84 | for idx in tqdm(range(frames)): 85 | 86 | # run img2img 87 | cur_img = await img2img(cur_img, 1.0, idx) 88 | 89 | w.add_image(np.array(cur_img)) 90 | 91 | t = create_transform(angle_speed, scale_speed, out_r) 92 | # transform image 93 | cur_img = cur_img.transform( 94 | out_r, 95 | Image.Transform.AFFINE, 96 | (t[0][0], t[0][1], t[0][2], t[1][0], t[1][1], t[1][2]), 97 | resample=Image.Resampling.BILINEAR) 98 | 99 | asyncio.run(main()) -------------------------------------------------------------------------------- /python/vid2vid/README.md: -------------------------------------------------------------------------------- 1 | # vid2vid 2 | 3 | Style video using stable diffusion with [computerender](https://computerender.com). 4 | 5 | 6 | 7 | ## 1. Setup 8 | You can install the python dependencies by running: 9 | 10 | ```bash 11 | pip install -r requirements.txt 12 | ``` 13 | 14 | Install ffmpeg for: 15 | 16 | Linux 17 | ```bash 18 | apt install ffmpeg 19 | ``` 20 | Macos: 21 | ```bash 22 | brew install ffmpeg 23 | ``` 24 | Windows: 25 | https://ffmpeg.org/download.html 26 | 27 | ## 2. API Key 28 | You can get an API key by making an account at https://computerender.com/account.html 29 | To make your key visible to the python client, you can add it as an environment variable: 30 | ```bash 31 | export CR_KEY=sk_your_key_here 32 | ``` 33 | Or alternatively provide it when initializing the client in the python script: 34 | ```python 35 | cr = Computerender("sk_your_key_here") 36 | ``` 37 | 38 | ## 3. Running the script 39 | It is a good idea to first create a short, trimmed version of your video that's just a few frames. 40 | This will be helpful for tuning parameters to get the right amount of modification to your video. 41 | Most importantly, the "strength" parameter will determine how much influence the effect has. 42 | 43 | Run the script: 44 | ```bash 45 | python vid2vid.py 46 | ``` 47 | 48 | ## 4. Post processing 49 | To produce the final output, the video was imported into adobe premiere and slowed using "optical flow" as the frame interpolation. It is also possible to do this optical flow interpolation using ffmpeg. 50 | Following the method used in this article: 51 | https://blog.programster.org/ffmpeg-create-smooth-videos-with-frame-interpolation 52 | One can do: 53 | ```bash 54 | ffmpeg \ 55 | -i sd-output.mp4 \ 56 | -crf 10 \ 57 | -vf "minterpolate=fps=60:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1" \ 58 | sd-output-smooth.mp4 59 | ``` 60 | You may need to first edit the speed or framerate of the video to get good results this way. 61 | 62 | -------------------------------------------------------------------------------- /python/vid2vid/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/computerender/tutorials/d65208541f9ac59ea3ff321d10928b0b72ad849a/python/vid2vid/example.gif -------------------------------------------------------------------------------- /python/vid2vid/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | Pillow 3 | tqdm 4 | mediapy 5 | computerender -------------------------------------------------------------------------------- /python/vid2vid/vid2vid.py: -------------------------------------------------------------------------------- 1 | from io import BytesIO 2 | import asyncio 3 | from computerender import Computerender 4 | from tqdm import tqdm 5 | from PIL import Image 6 | import numpy as np 7 | from mediapy import VideoReader, VideoWriter 8 | 9 | input_file = "IMG_0068.MOV" # <-- put your video here 10 | output_file = "sd-output.mp4" 11 | prompt = "a royal prince playing the guitar in magnificent room, victorian painting, highly detailed" 12 | strength = 0.5 # How strong the styling effect should be (range 0.1-1.0) 13 | seed = 200 # Change this to get a different generation using the same parameters 14 | guidance = 13.0 # How much the model should try to stick to the prompt (range 0-20) 15 | iterations = 50 16 | output_res = (512,512) 17 | out_r = (output_res[1], output_res[0]) 18 | parallel_jobs = 4 19 | 20 | # using the cropping method from here: 21 | # https://note.nkmk.me/en/python-pillow-square-circle-thumbnail/ 22 | def crop_center(pil_img, crop_width, crop_height): 23 | img_width, img_height = pil_img.size 24 | return pil_img.crop(((img_width - crop_width) // 2, 25 | (img_height - crop_height) // 2, 26 | (img_width + crop_width) // 2, 27 | (img_height + crop_height) // 2)) 28 | 29 | def crop_max_square(pil_img): 30 | return crop_center(pil_img, min(pil_img.size), min(pil_img.size)) 31 | 32 | cr = Computerender() 33 | 34 | async def img2img(arr, out_r): 35 | pil_image = crop_max_square(Image.fromarray(arr)).resize(out_r) 36 | img_bytes = BytesIO() 37 | pil_image.save(img_bytes, format="jpeg") 38 | img_out = await cr.generate( 39 | prompt, iterations=iterations, strength=strength, 40 | seed=seed, guidance=guidance, img=img_bytes.getvalue() 41 | ) 42 | return Image.open(BytesIO(img_out)) 43 | 44 | async def main(): 45 | with VideoReader(input_file) as r: 46 | with VideoWriter(output_file, shape=output_res, fps=r.fps, bps=r.bps) as w: 47 | cur_frames = [] 48 | for image in tqdm(r, total=r.num_images): 49 | cur_frames.append(image) 50 | if len(cur_frames) == parallel_jobs: 51 | imgs = await asyncio.gather(*[img2img(frame, out_r) for frame in cur_frames]) 52 | for sd_image in imgs: 53 | w.add_image(np.array(sd_image)) 54 | cur_frames = [] 55 | 56 | asyncio.run(main()) -------------------------------------------------------------------------------- /web/plain-js/PlainJS.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | Example using the   5 | computerender 6 |  API in a webpage with no libraries, just plain JS. 7 |
8 |
9 |
10 | 11 | 12 | 15 |
16 |
17 |

18 |

19 | 20 | 21 | -------------------------------------------------------------------------------- /web/plain-js/README.md: -------------------------------------------------------------------------------- 1 | # Plain JS example 2 | 3 | Basic web page demonstrating the [computerender](https://computerender.com) API using plain javascript. 4 | 5 | -------------------------------------------------------------------------------- /web/plain-js/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/computerender/tutorials/d65208541f9ac59ea3ff321d10928b0b72ad849a/web/plain-js/screenshot.png --------------------------------------------------------------------------------