Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Thumbs.db

# what the panel writes into the plugin folder while it runs
.eternal2x_*
.upflow2x_*

# the RIFE network's model is downloaded here on first use
models/
Expand Down
10 changes: 5 additions & 5 deletions Installer/Eternal2x.lua
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ local STOP_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_s
-- The frames marked on the clip go to the stage in this file. A long clip's
-- list does not fit on a Windows command line.
local MARKS_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_marks.txt")
local LOG_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_last_run.log")
local LOG_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".upflow2x_last_run.log")
-- The update check runs each time the panel opens, so it logs apart from
-- renders. Sharing a log wiped the render's, the one worth sending in.
local UPDATE_LOG_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_update.log")
Expand Down Expand Up @@ -323,7 +323,7 @@ local function stem_of(path)
end

-- What a render is called: its folder for a sequence of frames, its file
-- name for one file. nil for a path Eternal2x does not write.
-- name for one file. nil for a path Upflow2x does not write.
local function render_name(path)
return path:match("([^/\\]+)[/\\]frame_[%d%[%]%-]+%.png$")
or path:match("([^/\\]+)%.mkv$") or path:match("([^/\\]+)%.mp4$")
Expand Down Expand Up @@ -459,7 +459,7 @@ local function find_clip_path()
if not timeline then return nil, "No timeline is open." end

-- Resolve's API has no timeline selection. GetCurrentVideoItem is the clip
-- under the playhead, so that is the one Eternal2x works on.
-- under the playhead, so that is the one Upflow2x works on.
local item = nil
if timeline.GetCurrentVideoItem then
item = timeline:GetCurrentVideoItem()
Expand Down Expand Up @@ -1130,7 +1130,7 @@ local function refresh_source(keep)
return true
end

-- Eternal2x's own markers carry this, so analysing again replaces them and
-- Upflow2x's own markers carry this, so analysing again replaces them and
-- leaves every marker the editor placed.
local MARK_TAG = "eternal2x"

Expand Down Expand Up @@ -1978,7 +1978,7 @@ win:Show()

if REPO_ROOT == "" then
items.Meta.Text = "Plugin folder not configured."
set_status("Run Installer/install_eternal2x.py, then restart Resolve.")
set_status("Run Installer/install_upflow2x.py, then restart Resolve.")
else
refresh_source()
start_polling()
Expand Down
2 changes: 1 addition & 1 deletion Installer/Eternal2xLauncher.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ local function file_exists(path)
return true
end

-- Where Installer/install_eternal2x.py puts this script, for when Resolve
-- Where Installer/install_upflow2x.py puts this script, for when Resolve
-- reports the running script under a path map such as Scripts: that io.open
-- cannot follow.
local function installed_dir()
Expand Down
4 changes: 2 additions & 2 deletions Installer/gui_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
# drift. This runs standalone and from a PyInstaller bundle, where the repo
# root is not on the path, so fall back to importing the sibling module.
try:
from Installer.install_eternal2x import (
from Installer.install_upflow2x import (
_resolve_scripts_dir, remove_old_install, write_config)
except ImportError: # pragma: no cover - depends on how this was launched
sys.path.insert(0, str(Path(__file__).resolve().parent))
from install_eternal2x import (
from install_upflow2x import (
_resolve_scripts_dir, remove_old_install, write_config)

# ---------------------------------------------------------------------------
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions Pipeline/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


@dataclass
class Eternal2xConfig:
class Upflow2xConfig:
"""Everything the pipeline needs, in one place.

Defaults are tuned for hand-drawn animation, which is typically drawn on
Expand Down Expand Up @@ -53,10 +53,10 @@ def to_dict(self) -> dict:
return asdict(self)

@classmethod
def from_dict(cls, data: dict) -> "Eternal2xConfig":
def from_dict(cls, data: dict) -> "Upflow2xConfig":
known = {f for f in cls.__dataclass_fields__}
return cls(**{k: v for k, v in (data or {}).items() if k in known})


# Kept so older saved settings and the previous CLI flags still load.
UpscaleConfig = Eternal2xConfig
UpscaleConfig = Upflow2xConfig
8 changes: 4 additions & 4 deletions Pipeline/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import cv2
import numpy as np

from Pipeline.config import Eternal2xConfig
from Pipeline.config import Upflow2xConfig
from Pipeline.dedupe import DedupePlan, noise_threshold, plan_from_scores, output_time_map
from Pipeline.interpolate import frames_are_a_cut, is_a_cut, shot_change, upscale

Expand Down Expand Up @@ -246,7 +246,7 @@ def _require_constant_rate(cap: _ClipReader, fps: float, path: Path) -> None:

def frame_difference_scores(
path: Path,
cfg: Eternal2xConfig,
cfg: Upflow2xConfig,
*,
progress: Optional[ProgressFn] = None,
frames: FrameRange = None,
Expand Down Expand Up @@ -303,7 +303,7 @@ def frame_difference_scores(

def analyse_video(
path: Path,
cfg: Eternal2xConfig,
cfg: Upflow2xConfig,
*,
progress: Optional[ProgressFn] = None,
frames: FrameRange = None,
Expand Down Expand Up @@ -407,7 +407,7 @@ def render_plan(
source: Path,
plan: DedupePlan,
output: Path,
cfg: Eternal2xConfig,
cfg: Upflow2xConfig,
*,
progress: Optional[ProgressFn] = None,
sequence: Optional[bool] = None,
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ install below, which does the same job.

```
python -m pip install numpy opencv-python
python Installer/install_eternal2x.py
python Installer/install_upflow2x.py
```

Use `python3` on macOS. The installer records the Python that runs it, so
Expand Down Expand Up @@ -132,7 +132,7 @@ Markers on the timeline's ruler do not, so beat markers are safe there. You can
skip Analyse and mark the frames yourself. A clip with no markers at all is
rendered from the drawings Upflow2x finds on its own.

![The Upflow2x panel in DaVinci Resolve Studio after a render. The rebuilt clip sits on V2, lined up above the original on V1.](https://upflow2x.com/assets/demo/resolve.jpg)
![The Upflow2x panel open in DaVinci Resolve Studio, with Hero walk.mp4 on V1 and its render on V2.](https://upflow2x.com/assets/demo/resolve.jpg)

The render runs in the background and the panel shows progress and the time
left, so Resolve stays usable while it works. **Stop** ends it early. When it finishes, the rebuilt
Expand Down Expand Up @@ -220,7 +220,7 @@ afterwards.
| Problem | Fix |
|---|---|
| Resolve says you need Studio | Since 19.1 the free edition blocks script panels. Upflow2x needs Studio. |
| Clicking Upflow2x does nothing, or "Plugin folder not configured" | The plugin folder moved after installing, and Workspace → Console says `UI script not found`. Re-run `python Installer/install_eternal2x.py` from where it is now. |
| Clicking Upflow2x does nothing, or "Plugin folder not configured" | The plugin folder moved after installing, and Workspace → Console says `UI script not found`. Re-run `python Installer/install_upflow2x.py` from where it is now. |
| "Could not reach Resolve" | Open the panel from Workspace → Scripts, not from a terminal. |
| "No clip under the playhead" | Move the playhead over the clip, and the panel picks it up. |
| "No duplicate frames. This clip is already on 1s." | The clip has no duplicated frames. It is live action, or already on 1s. |
Expand All @@ -229,7 +229,7 @@ afterwards.
| Progress seems stuck | Press **Refresh Progress**. If Python stopped, the panel says so and shows its last error. If a run was interrupted, press **Reset**. |
| Resolve would not import the render | The render still finished. The panel prints where it is, so drag it into your media pool. Switching Output to `Image sequence` usually avoids this. |
| Upscale skipped | Without a GPU the upscale is Super Scale, which needs Resolve Studio. |
| Something else | Email the panel's status text and the `.eternal2x_last_run.log` file from the plugin folder. |
| Something else | Email the panel's status text and the `.upflow2x_last_run.log` file from the plugin folder. |

## Development

Expand All @@ -251,7 +251,7 @@ the environment variables from Blackmagic's scripting README, then run
To cut a release, bump `VERSION` and push a matching tag:

```
git tag v0.3.1 && git push origin v0.3.1
git tag v0.5.0 && git push origin v0.5.0
```

The release workflow builds the archives, publishes them, checks the published
Expand Down
6 changes: 3 additions & 3 deletions Stages/resolve_smooth.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# able to tell the panel so, or the panel waits on a run that never started.
try:
from Pipeline import resolve_bridge as bridge
from Pipeline.config import Eternal2xConfig
from Pipeline.config import Upflow2xConfig
from Pipeline.dedupe import plan_from_marks
from Pipeline.render import SourceError, analyse_video, probe_video, render_plan
except ImportError as exc:
Expand Down Expand Up @@ -276,8 +276,8 @@ def build_parser() -> argparse.ArgumentParser:
return parser


def config_from_args(args) -> Eternal2xConfig:
cfg = Eternal2xConfig()
def config_from_args(args) -> Upflow2xConfig:
cfg = Upflow2xConfig()
if args.threshold is not None:
cfg.duplicate_threshold = args.threshold
if args.base_hold:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0
0.5.0
Binary file modified docs/assets/demo/frames.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/demo/resolve.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/contact.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ <h1>Contact</h1>
<p class="hint">Many errors already have a fix under <a href="help.html#troubleshooting">Troubleshooting</a>.</p>
<div class="pair">
<label class="field"><span>Resolve version</span><input type="text" name="resolve version" placeholder="20.2 Studio"></label>
<label class="field"><span>Upflow2x version</span><input type="text" name="plugin version" placeholder="0.4.0"></label>
<label class="field"><span>Upflow2x version</span><input type="text" name="plugin version" placeholder="0.5.0"></label>
</div>
<label class="field"><span>Computer and graphics card</span><input type="text" name="computer" placeholder="Windows 11, RTX 4070"></label>
<label class="field"><span>What the panel said</span><textarea name="panel said" rows="2"></textarea></label>
Expand Down
6 changes: 3 additions & 3 deletions docs/help.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ <h3>Open it in Resolve</h3>
<h3>If the installer window doesn't open</h3>
<p>Your Python was built without Tk. These two commands do the same job from the same folder, without a window. Then restart Resolve.</p>
<div class="code"><code>python -m pip install numpy opencv-python</code></div>
<div class="code"><code>python Installer/install_eternal2x.py</code></div>
<div class="code"><code>python Installer/install_upflow2x.py</code></div>
</section>

<section id="macos" aria-labelledby="macos-title">
Expand Down Expand Up @@ -122,7 +122,7 @@ <h3>Open it in Resolve</h3>
<h3>If the installer window doesn't open</h3>
<p>Run these from the same folder instead, then restart Resolve.</p>
<div class="code"><code>python3 -m pip install numpy opencv-python</code></div>
<div class="code"><code>python3 Installer/install_eternal2x.py</code></div>
<div class="code"><code>python3 Installer/install_upflow2x.py</code></div>
</section>

<section id="usage" aria-labelledby="usage-title">
Expand Down Expand Up @@ -231,7 +231,7 @@ <h2 id="troubleshooting-title">Troubleshooting</h2>
<summary>Progress seems stuck</summary>
<div class="answer">
<p>Press Refresh Progress. If the panel says Python hasn't started, or that there's been no progress for a few minutes, the run stopped. Press Reset and run it again.</p>
<p>For anything else, email us the panel's status text and the <code>.eternal2x_last_run.log</code> file from the plugin folder.</p>
<p>For anything else, email us the panel's status text and the <code>.upflow2x_last_run.log</code> file from the plugin folder.</p>
</div>
</details>
<details>
Expand Down
4 changes: 2 additions & 2 deletions promo/film/meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "eternal2x-brag",
"name": "eternal2x-brag",
"id": "upflow2x-brag",
"name": "upflow2x-brag",
"createdAt": "2026-10-24T20:41:42.478Z"
}
2 changes: 1 addition & 1 deletion promo/film/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "eternal2x-brag",
"name": "upflow2x-brag",
"private": true,
"type": "module",
"scripts": {
Expand Down
Binary file removed public/logo/Eternal 2x logo 01.png
Binary file not shown.
10 changes: 5 additions & 5 deletions release/upflow2x-mac/Installer/Eternal2x.lua
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ local STOP_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_s
-- The frames marked on the clip go to the stage in this file. A long clip's
-- list does not fit on a Windows command line.
local MARKS_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_marks.txt")
local LOG_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_last_run.log")
local LOG_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".upflow2x_last_run.log")
-- The update check runs each time the panel opens, so it logs apart from
-- renders. Sharing a log wiped the render's, the one worth sending in.
local UPDATE_LOG_PATH = join_path(REPO_ROOT ~= "" and REPO_ROOT or root, ".eternal2x_update.log")
Expand Down Expand Up @@ -323,7 +323,7 @@ local function stem_of(path)
end

-- What a render is called: its folder for a sequence of frames, its file
-- name for one file. nil for a path Eternal2x does not write.
-- name for one file. nil for a path Upflow2x does not write.
local function render_name(path)
return path:match("([^/\\]+)[/\\]frame_[%d%[%]%-]+%.png$")
or path:match("([^/\\]+)%.mkv$") or path:match("([^/\\]+)%.mp4$")
Expand Down Expand Up @@ -459,7 +459,7 @@ local function find_clip_path()
if not timeline then return nil, "No timeline is open." end

-- Resolve's API has no timeline selection. GetCurrentVideoItem is the clip
-- under the playhead, so that is the one Eternal2x works on.
-- under the playhead, so that is the one Upflow2x works on.
local item = nil
if timeline.GetCurrentVideoItem then
item = timeline:GetCurrentVideoItem()
Expand Down Expand Up @@ -1130,7 +1130,7 @@ local function refresh_source(keep)
return true
end

-- Eternal2x's own markers carry this, so analysing again replaces them and
-- Upflow2x's own markers carry this, so analysing again replaces them and
-- leaves every marker the editor placed.
local MARK_TAG = "eternal2x"

Expand Down Expand Up @@ -1978,7 +1978,7 @@ win:Show()

if REPO_ROOT == "" then
items.Meta.Text = "Plugin folder not configured."
set_status("Run Installer/install_eternal2x.py, then restart Resolve.")
set_status("Run Installer/install_upflow2x.py, then restart Resolve.")
else
refresh_source()
start_polling()
Expand Down
2 changes: 1 addition & 1 deletion release/upflow2x-mac/Installer/Eternal2xLauncher.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ local function file_exists(path)
return true
end

-- Where Installer/install_eternal2x.py puts this script, for when Resolve
-- Where Installer/install_upflow2x.py puts this script, for when Resolve
-- reports the running script under a path map such as Scripts: that io.open
-- cannot follow.
local function installed_dir()
Expand Down
4 changes: 2 additions & 2 deletions release/upflow2x-mac/Installer/gui_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
# drift. This runs standalone and from a PyInstaller bundle, where the repo
# root is not on the path, so fall back to importing the sibling module.
try:
from Installer.install_eternal2x import (
from Installer.install_upflow2x import (
_resolve_scripts_dir, remove_old_install, write_config)
except ImportError: # pragma: no cover - depends on how this was launched
sys.path.insert(0, str(Path(__file__).resolve().parent))
from install_eternal2x import (
from install_upflow2x import (
_resolve_scripts_dir, remove_old_install, write_config)

# ---------------------------------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions release/upflow2x-mac/Pipeline/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


@dataclass
class Eternal2xConfig:
class Upflow2xConfig:
"""Everything the pipeline needs, in one place.

Defaults are tuned for hand-drawn animation, which is typically drawn on
Expand Down Expand Up @@ -53,10 +53,10 @@ def to_dict(self) -> dict:
return asdict(self)

@classmethod
def from_dict(cls, data: dict) -> "Eternal2xConfig":
def from_dict(cls, data: dict) -> "Upflow2xConfig":
known = {f for f in cls.__dataclass_fields__}
return cls(**{k: v for k, v in (data or {}).items() if k in known})


# Kept so older saved settings and the previous CLI flags still load.
UpscaleConfig = Eternal2xConfig
UpscaleConfig = Upflow2xConfig
8 changes: 4 additions & 4 deletions release/upflow2x-mac/Pipeline/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import cv2
import numpy as np

from Pipeline.config import Eternal2xConfig
from Pipeline.config import Upflow2xConfig
from Pipeline.dedupe import DedupePlan, noise_threshold, plan_from_scores, output_time_map
from Pipeline.interpolate import frames_are_a_cut, is_a_cut, shot_change, upscale

Expand Down Expand Up @@ -246,7 +246,7 @@ def _require_constant_rate(cap: _ClipReader, fps: float, path: Path) -> None:

def frame_difference_scores(
path: Path,
cfg: Eternal2xConfig,
cfg: Upflow2xConfig,
*,
progress: Optional[ProgressFn] = None,
frames: FrameRange = None,
Expand Down Expand Up @@ -303,7 +303,7 @@ def frame_difference_scores(

def analyse_video(
path: Path,
cfg: Eternal2xConfig,
cfg: Upflow2xConfig,
*,
progress: Optional[ProgressFn] = None,
frames: FrameRange = None,
Expand Down Expand Up @@ -407,7 +407,7 @@ def render_plan(
source: Path,
plan: DedupePlan,
output: Path,
cfg: Eternal2xConfig,
cfg: Upflow2xConfig,
*,
progress: Optional[ProgressFn] = None,
sequence: Optional[bool] = None,
Expand Down
Loading
Loading