Hi there! I'm Charlotte, a journalist with The Steambird~
Art credit: Kuromitsuri Tomato
Who else would archive Teyvat's cutscenes but its best journalist?
Charlotte is a Genshin Impact utility that losslessly decrypts .usm cutscene files into playable .mkv videos, covering all known cutscenes from versions 1.0 through 7.0. Charlotte is also able to retrieve keys directly from USM file itself, although an explicitly defined key is still preferred for processing speed.
This project is heavily inspired by GI-cutscenes. Charlotte not only rebuilds the workflow at a higher level, it also has various optimizations to the decryption algorithm to be significantly more efficient (and even faster than the original implementation despite being on Python). Charlotte also add extras with tons of QoLs (see below), VapourSynth processing, and a GUI. Also credits to UsmDiviner for inspiring me with the key guessing algorithm.
If you have missing keys, pull requests are welcome.
Disclaimer: This tool is purely for educational purpose and aims to archive already released game content.
- Losslessly decrypt
.usminto.ivfvideo and.hcaEN, CN, JP, KR audio tracks - Significantly improved decryption algorithm compared to GI-cutscenes implementation
- Key recovery for USM files without a key
- Convert
.hcaaudio to lossless.flac, or.opus(VBR 256kbps) for smaller files - Convert
.srtsubtitles into styled.assin 15 languages with matching official cutscene subtitle style and fonts - Mux all tracks into
.mkv, with selectable default audio and subtitle tracks - Automatically syncs the full subtitle collection (all 15 languages) from DimBreath
- Automatically fetches new keys from upstream
- Automatically get fonts from the game directory if possible
- VapourSynth pipeline for post-processing quality improvements
- Bundled lightweight custom FFmpeg build at only ~15MB
- Built-in updater that checks for a newer release and installs it in place
- Graphical User Interface (coming soon)
VapourSynth filter scripts take a lot of time to write to ensure quality, hence they will be slowly added over time. If you have encoding knowledge, contributions are welcome!
I should also mention that the VapourSynth filters are extremely heavy on CPU and GPU (to a lesser degree), so it's recommended to have a powerful machine for optimal performance.
- Download
charlotte.exefrom the latest release. - Locate
.usmfiles at:
[Game Directory]\Genshin Impact game\GenshinImpact_Data\StreamingAssets\VideoAssets\StandaloneWindows64
Note: the availability of older cutscenes depends on your local game files and resource cleanup history.
charlotte [PATHS...] [OPTIONS]PATHS is one or more .usm files and/or directories containing .usm files.
Example:
charlotte "USM\Cs_Cutscene_Something_Girl.usm" -vs -ncThis decrypts the cutscene, applies the VapourSynth filter script, and writes to output/Cs_EQHDJ005_HaiDengJie_Girl/Cs_EQHDJ005_HaiDengJie_Girl.mkv without deleting intermediate files.
Process several files and/or directories at once:
charlotte "USM\Cs_A.usm" "USM\Cs_B.usm" "USM\Cs_More_Cutscenes.usm" -o outputTo check what is available for your files (decryption key, local subtitles, VapourSynth script) without processing anything:
charlotte "USM\Cs_Cutscene_Something_Girl.usm" --probeTo recover key straight from the USM file and report them without demuxing or converting:
charlotte "USM\Cs_Cutscene_Something_Girl.usm" --crackTo check for a newer release, and install it in place after confirmation:
charlotte --updateFor help:
charlotte --helpTip: If you're running with -vs flag, for higher encoding speed, setting Python and FFmpeg in Task Manager to high priority can help. Alternatively, you can leave the terminal on the front so that Windows' Process Scheduling Priority will prioritize Charlotte.
| Type | Flag | Alias | Description |
|---|---|---|---|
| Argument | PATHS... |
- |
One or more .usm files and/or directories containing .usm files. |
| Option | --output [DIR] |
-o |
Output directory (default: output). |
| Option | --flat |
-f |
Write {name}.mkv directly into the output directory instead of a per-cutscene subfolder. |
| Option | --skip-existing |
-se |
Skip any file whose output .mkv already exists. |
| Option | --no-cleanup |
-nc |
Keep intermediate files (.ivf, .hca, .ass, etc.). |
| Option | --audio-codec [CODEC] |
-ac |
Audio codec for muxed tracks: flac (default, lossless) or opus (smaller; requires an FFmpeg build with libopus). |
| Option | --default-audio [LANG] |
-da |
Audio language flagged as default in the .mkv: zh, en, ja (default), ko. |
| Option | --default-sub [CODE] |
-ds |
Subtitle language flagged as default: chs, cht, de, en (default), es, fr, id, it, jp, kr, pt, ru, th, tr, vi. |
| Option | --key [KEY] |
-k |
Manually input a key for a single file |
| Option | --vapoursynth |
-vs |
Apply a matching VapourSynth filter script from vs/. |
| Option | --crf [VALUE] |
-crf |
x265 CRF value for VapourSynth output (default: 13.5). |
| Option | --preset [PRESET] |
-preset |
x265 preset for VapourSynth output (default: slower). |
| Option | --x265-params [PARAMS] |
-x265 |
Custom x265 params (colon-separated). Overrides the built-in defaults below. |
| Option | --probe |
-p |
Only report what is available for each file (decryption key, local subtitles, VapourSynth script). Read-only: nothing is processed or fetched. |
| Option | --crack |
-c |
Recover key from USM file and report it, without demuxing or converting. |
| Option | --json |
-json |
Emit newline-delimited JSON events on stdout for a GUI/automation frontend. |
| Option | --update |
-u |
Check GitHub for a newer release and update. |
| Option | --version |
-v |
Print the Charlotte version and exit. |
When neither --crf, --preset, nor --x265-params is set, the following x265 params are applied automatically:
keyint=300:min-keyint=30:no-open-gop=1:ref=6:bframes=8:lookahead-slices=0:rc-lookahead=60:aq-mode=3:aq-strength=0.75:qcomp=0.72:cbqpoffs=-2:crqpoffs=-2:no-cutree=1:rd=4:psy-rd=2.0:psy-rdoq=1.7:max-merge=5:no-strong-intra-smoothing=1:tskip=1:deblock=-2,-2:no-sao=1:no-sao-non-deblock=1
Setting --crf or --preset suppresses these params, letting x265 use its own defaults for everything else. To combine custom crf/preset with custom x265 params, use --x265-params explicitly (it always takes full precedence).
- Python 3.14 or higher
- uv
- FFmpeg (see below)
Install dependencies:
uv syncRun the project:
uv run main.py USM/Cs_EQHDJ005_HaiDengJie_Boy.usm -vs -nc
For flag options, refer to the Parameters section.
The bundled ffmpeg.exe is a lightweight custom build. To rebuild it:
- Set up media-autobuild_suite.
- Copy
ffmpeg_options.txtfrom the repo root to<suite>/build/ffmpeg_options.txt. - To force a rebuild after changing options, delete
<suite>/local64/bin-video/ffmpeg.exebefore runningmedia-autobuild_suite.bat. - Copy the resulting
<suite>/local64/bin-video/ffmpeg.exeto the repo root.
If you don't want to do any of that, you can just get my prebuilt from here.
uv run pyinstaller charlotte.specIf you enjoyed using Charlotte, your support would mean so much to me. It keeps me motivated to invest more time into the project and keep it alive for as long as I can.
