Skip to main content

VideoTubeEditor - Join two local videos, and cut, speed, or boomerang an MP4

Version License CIAO Stars Python PyPI

VideoTubeEditor keeps the VideoJoin architecture and adds the VideoSpeed edit steps. It concatenates two video files from the current directory using FFmpeg (stream copy first, then a fail-closed re-encode). It also cuts an MP4, changes its length, and can append a boomerang or a repeat. Intermediate files are published with shutil.move.

On a terminal with an X11 display (DISPLAY set, including ssh -X), starting it with no arguments opens a window. Edit and Join are two groups: one is on screen while the other is hidden. The labels join and edit sit on that group, sharing its left edge and width. The row for the group on screen is highlighted, and the highlight meets the top of the group. Each group splits left and right. The left side is the source or sources and the settings. The right side is the output. Edit plays an MP4, with the elapsed time on the left of the time bar as 00:00.00, and with Start, Pause, Stop, jump, Mark start, and Mark end. Percent stays 20–200. The tail choices are None, Boomerang, and Repeat, and None starts selected. The window’s top menu shows join, edit, system-log, language, self-management, and Exit. Button names and the other window labels follow the language chosen there. The clock 00:00.00, the folder path, and the About page stay in their current form. The edit right side also plays the generated file, with that elapsed time bar and with Play and Stop. When Run starts, that generated player is cleared and its controls are disabled. When the run finishes and the file is on disk, the player loads the file and the controls are enabled. Join has two Select file buttons, with Video 1 above Video 2. Each source has a player under its path, and the generated file has a third player on the right. Those three players show the elapsed time on the time bar and have Play and Stop. video-tube-editor tui opens the text menu and leaves that menu as it is. With no display, a bare start still opens the text menu. join is row 1. edit is row 2. Neither the window nor the menu starts a job by itself, and neither calls pip.

Features

  • Text menu on a terminal: join (1), edit (2), system-log (3), language (4), self-management (8), and Exit (9)
  • The first row shows the current folder and a local clock (HH:MM:SS) when the row has room
  • Numbered rows line up. A rounded input box sits along the bottom, as wide as the terminal, with the name and version on the status line under the box
  • system-log (3) opens view-log, clear-log, and log-folder. language (4) picks the menu language and the window labels. self-management (8) opens version, about, and the pip lifecycle rows
  • Interactive pick of first and second video (same file cannot be chosen twice)
  • Discovers .mp4, .mov, .mkv, .avi, .m4v in the current working directory (sorted case-insensitively)
  • Stream-copy join first (ffmpeg concat demuxer); re-encode fallback (libx264 CRF 18, AAC 192k)
  • Fail-closed: no success message if both paths fail
  • Unique temp list + media intermediates; cleanup on success and failure
  • Publish intermediates with shutil.move (same FS rename; cross-mount copy+delete)
  • FFmpeg on PATH checked before joining
  • Console scripts video-tube-editor, video-join, and video-speed, and module entry python -m VideoTubeEditor
  • Typed verbs: help, version, about, hello, tui, join, list-videos, edit, list-mp4, self-install, version-check, self-update, self-uninstall, setup
  • X11 window when a bare start sees DISPLAY. The window uses the host GTK 4 and GStreamer packages. They are not pip dependencies. about reports whether this Python can import them. On Windows, a missing library names video-tube-editor tui and the page does not install packages

Advantages

  1. Dual-mode interface. The menu asks for two indexes and an output name on join, and for a folder, a file, a cut, a length percent, and a tail of none, boomerang, or repeat on edit. A typed verb asks the same questions. The person does not write an FFmpeg graph. Join tries stream copy, then re-encodes if copy fails. Edit can also run from --file, --start, and --end, and --json prints one object without opening the menu. With no arguments on a terminal, the text menu opens. With no terminal and no verb, the program prints help and returns 0. Direct join with no terminal exits non-zero.
  2. Built-in languages. Row 4 lists thirteen languages: English, Simplified Chinese, Traditional Chinese, Spanish, Arabic, French, Portuguese, Russian, German, Japanese, Korean, Dutch, and Greek. The choice is saved for the next run.
  3. USB-safe staging. Intermediate files are written beside the output when that folder can be written, including on a removable drive. The finished file is published with shutil.move. When that folder cannot be written, the stage uses the system temporary directory.
  4. Lifecycle and diagnostics. version-check, self-update, self-install, and self-uninstall are menu rows 84–87 and typed verbs. self-uninstall on the command line needs --force. They call pip and do not use root. system-log (3) views a log, clears a log, and shows the log folder. about (83) stays in English.
Feature Raw FFmpeg CLI Typical Python wrappers (moviepy) VideoTubeEditor
Learning curve A concat or filter graph the person writes A Python script Text menu, or two file numbers and an output name, or edit flags
Non-interactive Native command line A custom script Typed verbs. No terminal and no verb: help, return 0. Direct join with no terminal: non-zero. --json for an edit job or for help
Menu languages None None Thirteen, kept for the next run
Temporary files You choose the paths Often the system temporary directory Beside the output when that folder can be written. Otherwise the system temporary directory. Publish with shutil.move
Self-management The system package manager pip from outside the tool Built-in version-check, self-update, self-install, and self-uninstall
Diagnostics and logs The encode stream A logging setup in the script system-log (row 3) and about (83), in English

Quick Installation

System requirement: FFmpeg must be installed and available as ffmpeg on your PATH. The package does not install FFmpeg via pip.

Python dependencies: ChronicleLogger>=1.3.1 and opencv-python-headless>=5.0.0.93 (both required). Pip installs them with VideoTubeEditor. Python 3.11 or newer.

PyPI (registry)

pip install VideoTubeEditor

This installs the console entries video-tube-editor, video-join, and video-speed, and the package VideoTubeEditor. Packaging name SSOT is pyproject.toml [project].name = VideoTubeEditor. This tree is 1.0.1. The source home is https://github.com/cloudgen/VideoTubeEditor. The PyPI badge above shows the live index.

Local install (checkout)

From a checkout (editable / unreleased work):

git clone git@github.com:cloudgen/VideoTubeEditor.git
# or: git clone https://github.com/cloudgen/VideoTubeEditor.git
cd VideoTubeEditor
python3 -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -e .

Main menu

After install, on a terminal, video-tube-editor with no arguments prints this screen. video-join and video-speed open the same screen. The verb is bold and the note after the colon is italic. 9 leaves. 0 on a submenu goes back. After a command finishes, the main menu is shown again. A number that is not on the list prints an error and lets you choose again.

Picture of the English menu. Current directory /tmp/clips. The rows are the text the menu paints. The frame is the 80-column box.

$ video-tube-editor
Path: /tmp/clips                                                       12:06:45

1. **join**           : *pick two videos in this folder and concatenate*
2. **edit**           : *cut, speed, and optional boomerang or repeat*
3. **system-log**     : *view, clear, and the log folder*
4. **language**       : *display language for this menu*
8. **self-management**: *version, about, and pip lifecycle*
9. **Exit**           : *leave*




╭─────────────────────────────────────────────────────────────────────────────╮
│ >                                                                           │
╰─────────────────────────────────────────────────────────────────────────────╯
  VideoTubeEditor 1.0.1  │  main menu  │  Up/Down  •  Enter

system-log (3):

Path: /tmp/clips                                                       12:06:45

31. **view-log**  : *list a log file and show it*
32. **clear-log** : *empty one log file*
33. **log-folder**: *show the log folder*
 0. **Back**      : *return to the main menu*




╭─────────────────────────────────────────────────────────────────────────────╮
│ >                                                                           │
╰─────────────────────────────────────────────────────────────────────────────╯
  VideoTubeEditor 1.0.1  │  system-log  │  Up/Down  •  Enter

language (4). The short on each language row is that language’s own name. Numbers 40 and 54–59 are not printed. 0 goes back and does not save.

Path: /tmp/clips                                                       12:06:46

41. **English**   : *use English for this menu*
42. **简体中文**      : *use 简体中文 for this menu*
43. **繁體中文**      : *use 繁體中文 for this menu*
44. **Español**   : *use Español for this menu*
45. **العربية**   : *use العربية for this menu*
46. **Français**  : *use Français for this menu*
47. **Português** : *use Português for this menu*
48. **Русский**   : *use Русский for this menu*
49. **Deutsch**   : *use Deutsch for this menu*
50. **日本語**       : *use 日本語 for this menu*
51. **한국어**       : *use 한국어 for this menu*
52. **Nederlands**: *use Nederlands for this menu*
53. **Ελληνικά**  : *use Ελληνικά for this menu*
 0. **Back**      : *return to the main menu*

╭─────────────────────────────────────────────────────────────────────────────╮
│ >                                                                           │
╰─────────────────────────────────────────────────────────────────────────────╯
  VideoTubeEditor 1.0.1  │  language  │  Up/Down  •  Enter

self-management (8):

Path: /tmp/clips                                                       14:05:09

82. **version**       : *show the installed version*
83. **about**         : *version, FFmpeg, and this computer*
84. **version-check** : *compare this install with pip*
85. **self-update**   : *upgrade this package with pip*
86. **self-uninstall**: *remove this package with pip*
87. **self-install**  : *install this package with pip*
 0. **Back**          : *return to the main menu*

╭─────────────────────────────────────────────────────────────────────────────╮
│ >                                                                           │
╰─────────────────────────────────────────────────────────────────────────────╯
  VideoTubeEditor 1.0.1  │  self-management  │  Up/Down  •  Enter

Choose a number, or type the command name in the box. The block caret appears in that box while it is focused.

Usage

video-tube-editor
# or
python -m VideoTubeEditor
# video-join and video-speed call the same entry

On a terminal with DISPLAY set, that opens the window. video-tube-editor tui opens the main menu above, including when DISPLAY is set. On a terminal with no DISPLAY, a bare start opens that menu. It does not ask for videos yet, and it does not call pip. With no terminal, the same command prints help and returns 0.

join (1), or video-tube-editor join on a terminal, stays on the screen and asks in the bottom box:

  1. First video number
  2. Second video number from the remaining list
  3. Output name (Enter uses {stem1} + {stem2}.mp4)

Esc returns to the main menu and does not join. Fewer than two eligible videos fails closed: FFmpeg does not run. video-tube-editor join with no terminal exits non-zero and tells you to use a terminal. Join does not cut, speed, or boomerang.

edit (2), or video-tube-editor edit on a terminal, asks for a folder, then one MP4, then the start, the end, the length percent (Enter uses 100), and a tail. The tail is none (play once), boomerang (append the reverse), or repeat (append the clip so it plays twice). Enter uses none. A script can pass the whole job:

video-tube-editor edit --file clip.mp4 --start 1 --end 5 --percent 50 --boomerang
video-tube-editor edit --file clip.mp4 --start 1 --end 5 --percent 50 --repeat
video-tube-editor list-mp4

--boomerang and --repeat together fail closed. The window offers the same three choices. None is the default.

list-mp4 lists MP4 files and does not encode. --json prints one object and does not open the menu.

video-tube-editor help
video-tube-editor version
video-tube-editor about
video-tube-editor hello
video-tube-editor list-videos
video-tube-editor version-check
video-tube-editor self-update
video-tube-editor self-install
video-tube-editor self-uninstall --force

version prints VideoTubeEditor 1.0.1 and does not call pip. about shows one English page: the product identity, a host check of this computer, and a star box. It does not install FFmpeg and it does not call pip. hello prints a one-line greeting and does not draw the menu. list-videos lists eligible names and does not join. help prints usage.

version-check runs python -m pip index versions VideoTubeEditor. self-update runs python -m pip install --upgrade VideoTubeEditor. self-install runs python -m pip install VideoTubeEditor. self-uninstall runs python -m pip uninstall -y VideoTubeEditor and needs --force on the command line. Those pip verbs do not use sudo. Empty arguments do not install or update.

Exit codes: non-zero if join is started with no terminal, fewer than two videos, FFmpeg is missing, or the join fails. Menu Exit (9) returns 0.

Import for scripts (thin entry):

from VideoTubeEditor import main
# interactive session; a terminal opens the text menu

Screenshots

Each heading is the file name. The paragraph is what that picture shows. These four pictures are the X11 window for package 1.0.1. A bare video-tube-editor on a terminal with DISPLAY set opens this window. The header follows the saved menu language. On these captures that language is Traditional Chinese, so the header reads 系統日誌, 語言, 自我管理, and 離開. English labels for those buttons are system-log, language, self-management, and Exit. The title is VideoTubeEditor 1.0.1. The project-root line names the current directory and does not carry a clock. Each player clock reads 00:00.00. A loaded source player shows a thumbnail strip under the picture. The generated player stays empty, and its Play and Stop stay disabled, until a finished file is on disk. Play and Stop do not start or stop FFmpeg. Run has not been pressed, so the bottom bar reads 處理 0%.

gui-edit.png

Edit is the group on screen. The window title is VideoTubeEditor 1.0.1. The edit tab is highlighted and shares the group's left edge. A framed line under the header shows 專案根目錄 (Project Root) and the current directory. 輸入影片 (Input Video) holds one MP4, 選擇檔案 (Select file), and a player at 00:00.00 of 00:18.04. A thumbnail strip sits under that picture. 剪輯控制 (Edit Controls) has 開始 (Start), 暫停 (Pause), 停止 (Stop), a jump field showing 00:00.00, and 前往 (Go To). 起點 (Start) is 00:00.00 with 標記起點 (Mark start). 終點 (End) is 00:18.04 with 標記終點 (Mark end). 百分比 (Percent) is 100. 循環選項 (Looping Options) has 無 (None) on, and 迴旋 (Boomerang) and 重複 (Repeat) off. The output name is video-1_cut0.0-18.0s_100pct.mp4. 執行 (Run) has not been pressed. 輸出與結果 (Output & Result) shows that name. 已產生 (Generated) is empty. 結果影片 (Resulting Video) is empty, shows 00:00.00 of 00:00.00, and its 播放 (Play) and 停止 (Stop) are disabled. The bottom bar reads 處理 0% (Process 0%).

Edit group, Traditional Chinese labels, generated player empty

gui-join.png

Join is the group on screen. The join tab is highlighted and shares the group's left edge. The same header, project-root line, and 處理 0% bar are on screen. 影片 1 (Video 1) and 影片 2 (Video 2) are loaded. The first player shows 00:00.00 of 00:18.04. The second shows 00:00.00 of 00:12.04. A thumbnail strip sits under each source picture. Each source has 播放 (Play) and 停止 (Stop). 輸出名稱 (Output name) is video-1 + video-2.mp4. The write line names the current directory and that file. 執行 (Run) has not been pressed. 已產生 (Generated) is empty. 結果影片 (Resulting Video) is empty, shows 00:00.00 of 00:00.00, and its Play and Stop are disabled.

Join group, two source players, generated player empty

gui-language.png

The language page lists the thirteen menu languages. The header stays in the saved language. join and edit stay above the list and neither is highlighted. The rows are 41 English, 42 简体中文, 43 繁體中文, 44 Español, 45 العربية, 46 Français, 47 Português, 48 Русский, 49 Deutsch, 50 日本語, 51 한국어, 52 Nederlands, and 53 Ελληνικά. The project-root line names the current directory. The bottom bar reads 處理 0% (Process 0%). Choosing a row saves that language for the next window and for the text menu.

Language list, 41 English through 53 Greek

gui-self-management.png

Self-management shows the numbered actions and no extra page under them. The buttons are 82 version, 83 about, 84 version-check, 85 self-update, 86 self-uninstall, and 87 self-install. The header stays in the saved language. join and edit stay above the buttons and neither is highlighted. The project-root line names the current directory. The bottom bar reads 處理 0% (Process 0%). 83 about opens the English about page. The pip rows call pip and do not use root. self-uninstall on the command line needs --force.

Self-management, rows 82 through 87

Examples

cd /path/to/folder/with/clips
video-tube-editor
video-tube-editor version

version prints VideoTubeEditor 1.0.1 and does not call pip. A run that is not the text menu can also print ChronicleLogger status lines above that. The text menu keeps those lines off the screen.

video-tube-editor join
video-tube-editor edit --file clip.mp4 --start 1 --end 5 --percent 100

The window pictures are in Screenshots. Join still prefers stream copy, then re-encode, and publishes the result with shutil.move.

Platform Compatibility

Platform Status
Linux Primary; tested development path
macOS Supported when Python + FFmpeg on PATH
Windows CLI verbs run when Python is installed. video-tube-editor setup installs the declared pip libraries and, on Windows, tries curses and FFmpeg. The picture window still needs an X11 DISPLAY and the host GTK 4 and GStreamer packages
Architectures Any with CPython + FFmpeg binary

The text menu needs a terminal and the curses module. When this Python cannot import curses, about, version, help, and hello still run, and opening the text menu says the module is missing. video-tube-editor setup installs ChronicleLogger>=1.3.1 and opencv-python-headless>=5.0.0.93 for this Python. On Windows it also tries the curses module and FFmpeg. It does not install GTK 4 or GStreamer. With no terminal and no verb, the program prints help and returns 0. It does not wait.

Contributing

  1. Keep product law under docs/requirements/ in sync when behavior changes.
  2. Prefer small, CIAO-safe changes; do not remove Protection Zones in the join publish path (staging / shutil.move) without explicit design.
  3. Version dual SSOT: bump pyproject.toml and src/VideoTubeEditor/__init__.__version__ together.
  4. Open issues and pull requests on GitHub.

License

MIT — see LICENSE.md. Also declared in pyproject.toml.

Last Update

2026-10-12 — 1.0.1: The distribution name is VideoTubeEditor. The console script is video-tube-editor. The module is python -m VideoTubeEditor. Aliases video-join and video-speed stay. Public home is cloudgen/VideoTubeEditor. The four pictures are captures of this window. The title is VideoTubeEditor 1.0.1. Version badge matches pyproject.toml and __version__.

2026-10-12 — 1.0.0: The distribution name is VideoEditor. The console script is video-editor. The module is python -m VideoEditor. Public home is cloudgen/VideoEditor. The four pictures are captures of this window. The title is VideoEditor 1.0.0. Version badge matches pyproject.toml and __version__.

2026-10-11 — 2.0.0: The X11 window adds a project-root line, Input Video, Edit Controls, Looping Options, Output & Result, and Resulting Video. Looping Options is three switches and starts on None. A process bar reads Process 0% until a finished file is on disk. The four pictures are captures of that window. Version badge matches pyproject.toml and __version__.

2026-10-10 — 1.1.0: Public home is cloudgen/VideoEditor. The pictures are the X11 window: edit, join, language, and self-management. A bare start on a terminal with DISPLAY set opens that window. Console scripts are video-editor, video-join, and video-speed. Version badge matches pyproject.toml and __version__. ChronicleLogger>=1.3.1 and opencv-python-headless>=5.0.0.93 are required.

Metadata

Release files for VideoTubeEditor 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for VideoTubeEditor 1.0.1
File Size Uploaded Provenance Actions
videotubeeditor-1.0.1.tar.gz 119.6 kB Without provenance Details for videotubeeditor-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for VideoTubeEditor 1.0.1
File Interpreter ABI Platform Actions
videotubeeditor-1.0.1-py3-none-any.whl Python 3 none any Details for videotubeeditor-1.0.1-py3-none-any.whl

Total release size: 216.6 kB

Release files / videotubeeditor-1.0.1.tar.gz

Download URL videotubeeditor-1.0.1.tar.gz
Size 119.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e95a11b2efe79ca23656286061a7fe072a371a47cea1e6b20768b270bbed4d84
BLAKE2b-256 checksum
How to use checksums
9f8ee6d844be996040dad1c00b42ab648ab026ba3c48139deb4c5ddb28f45f89
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Release files / videotubeeditor-1.0.1-py3-none-any.whl

Download URL videotubeeditor-1.0.1-py3-none-any.whl
Size 96.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e6da9fd694a72b3033480d91d69544c18d4ddea40396b1518098225870cf6b81
BLAKE2b-256 checksum
How to use checksums
728a7b95f8f5bf1a8c42baf0baff3d3f406ace85b624b98905740b7b9f74ca2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Security for VideoTubeEditor 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page