add video exporting

This commit is contained in:
Alex
2025-08-31 22:07:14 -07:00
parent 11a9af5778
commit 1c2400cb3f
6 changed files with 91 additions and 15 deletions
+25 -9
View File
@@ -4,19 +4,35 @@ This is a guide to populating the `data` working folder found in this applicatio
**This project will only repack audio on Reverse 3.07 properly.** **This project will only repack audio on Reverse 3.07 properly.**
## Table of Contents (sorted by descending time consumption) ## Table of Contents (sorted by descending time consumption)
1. [Song Audio](#song-audio-datamer_bgm) 1. [Videos](#videos-datamovies)
2. [Jackets](#jackets-datajackets) 2. [Song Audio](#song-audio-datamer_bgm)
3. [Metadata](#metadata-datamusicparametertable) 3. [Jackets](#jackets-datajackets)
4. [Charts](#charts-datamusicdata) 4. [Metadata](#metadata-datamusicparametertable)
5. [Charts](#charts-datamusicdata)
## Videos (`data/movies`)
*~4.1 GB*
If you want to export music videos, the process for doing so involves a **lot** of waiting; it's automated but took me ~1 hour to finish and used up all of my CPU bandwidth during that time, though I could do some steps while this ran.
Videos exported using this process may not play properly as mentioned in [this issue](https://github.com/muskit/WacK-Repackager/issues/2).
You will need [FFmpeg](https://www.ffmpeg.org/download.html) installed and on PATH.
1. Set the paths in `convert-videos.bat/sh` as needed:
- `video_path` to `app/WindowsNoEditor/Mercury/Content/Movie`
- `export_path` to `data/movies`
2. Run `convert-videos.bat/sh` to convert all .usm videos to .mp4 in your data folder.
- This script will take a **very** long time to finish.
## Song Audio (`data/MER_BGM`) ## Song Audio (`data/MER_BGM`)
*~18.8 GB for WAVs* *~18.8 GB WAVs*
Due to the audio indexing data in this project only done for **Reverse 3.07**, this process will only work for files of that version. Due to the audio indexing data in this project only done for **Reverse 3.07**, this process will only work for files of that version.
You will need the latest version of [Audio Cue Editor (ACE)](https://github.com/LazyBone152/ACE). You will need the latest version of [Audio Cue Editor (ACE)](https://github.com/LazyBone152/ACE).
For each of the files below located in `<WAC>/app/WindowsNoEditor/Mercury/Content/Sound/Bgm`... For each of the files below located in `app/WindowsNoEditor/Mercury/Content/Sound/Bgm`...
- MER_BGM.awb - MER_BGM.awb
- MER_BGM_V3_01.awb - MER_BGM_V3_01.awb
@@ -50,7 +66,7 @@ For each of the files below located in `<WAC>/app/WindowsNoEditor/Mercury/Conten
For this, you will need [UE Viewer](https://www.gildor.org/en/projects/umodel). For this, you will need [UE Viewer](https://www.gildor.org/en/projects/umodel).
1. Run `umodel_64.exe` and configure its Startup Options. 1. Run `umodel_64.exe` and configure its Startup Options.
- Set "Path to game files" to `<WAC>/app/WindowsNoEditor/Mercury/Content/UI/Textures/JACKET`. - Set "Path to game files" to `app/WindowsNoEditor/Mercury/Content/UI/Textures/JACKET`.
- Enable "Override game detection" and set it to "Unreal engine 4.19". - Enable "Override game detection" and set it to "Unreal engine 4.19".
- Click OK. - Click OK.
2. In the left panel, right click on "All packages", then click on "Export folder content". 2. In the left panel, right click on "All packages", then click on "Export folder content".
@@ -60,8 +76,8 @@ For this, you will need [UE Viewer](https://www.gildor.org/en/projects/umodel).
## Metadata (`data/MusicParameterTable.*`) ## Metadata (`data/MusicParameterTable.*`)
*<1 MB* *<1 MB*
In `<WAC>/app/WindowsNoEditor/Mercury/Content/Table/`, simply copy `MusicParameterTable.uasset` and `MusicParameterTable.uexp` into `data`. In `app/WindowsNoEditor/Mercury/Content/Table/`, simply copy `MusicParameterTable.uasset` and `MusicParameterTable.uexp` into `data`.
## Charts (`data/MusicData`) ## Charts (`data/MusicData`)
*~59.5 MB* *~59.5 MB*
Simply copy the `MusicData` folder at `<WAC>/app/WindowsNoEditor/Mercury/Content/` into `data`. Simply copy the `MusicData` folder at `app/WindowsNoEditor/Mercury/Content/` into `data`.
+7
View File
@@ -0,0 +1,7 @@
@echo off
:: Set paths here first before running!!!
set video_path="\app\WindowsNoEditor\Mercury\Content\Movie"
set export_path=".\data\movies"
for %%i in (%video_path%\*.usm) do ffmpeg -n -f mpegvideo -i "%%i" "%export_path%\%%~ni.mp4"
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
# Set paths here first before running!!!
video_path="App/WindowsNoEditor/Mercury/Content/Movie/"
output_path="./data/movies/"
for file in "$video_path"/*.usm; do
output_file="$output_path/$(basename "$file" .usm).mp4"
echo $file
echo $output_file
ffmpeg -n -f mpegvideo -i "$file" "$output_file"
done
+8
View File
@@ -66,4 +66,12 @@ public static class Consts
{Difficulty.Expert, "NotesDesignerExpert"}, {Difficulty.Expert, "NotesDesignerExpert"},
{Difficulty.Inferno, "NotesDesignerInferno"}, {Difficulty.Inferno, "NotesDesignerInferno"},
}; };
public static readonly IReadOnlyDictionary<Difficulty, string> DIFF_MOVIE_KEY = new Dictionary<Difficulty, string>()
{
{Difficulty.Normal, "MovieAssetName"},
{Difficulty.Hard, "MovieAssetNameHard"},
{Difficulty.Expert, "MovieAssetNameExpert"},
{Difficulty.Inferno, "MovieAssetNameInferno"},
};
} }
+38 -5
View File
@@ -2,8 +2,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using System.IO; using System.IO;
using Avalonia.Data.Converters;
using MercuryConverter.Data; using MercuryConverter.Data;
using MercuryConverter.UI.Views; using MercuryConverter.UI.Views;
using MercuryConverter.Utility;
using SaturnData.Notation.Serialization; using SaturnData.Notation.Serialization;
namespace MercuryConverter.ExportOperation; namespace MercuryConverter.ExportOperation;
@@ -43,14 +45,16 @@ public class Exporter
Console.WriteLine($"Exporting {song.Id} to {exportSongPath}"); Console.WriteLine($"Exporting {song.Id} to {exportSongPath}");
var entryCharts = song.GetEntryCharts(); var entryCharts = song.GetEntryCharts();
HashSet<string> processedAudio = new(); HashSet<string> finishedAudio = new();
HashSet<string> finishedMovies = new();
string prevMovie = "-";
foreach (var ec in entryCharts) foreach (var ec in entryCharts)
{ {
/// AUDIO /// /// AUDIO ///
var audioKey = ec.Item1.AudioPath; var audioKey = ec.Item1.AudioPath;
var audioExportFileName = $"{audioKey}.{options.AudioFormat.ToString().ToLower()}"; var audioExportFileName = $"{audioKey}.{options.AudioFormat.ToString().ToLower()}";
if (!processedAudio.Contains(audioKey) && Database.AudioPaths.ContainsKey(audioKey)) if (!finishedAudio.Contains(audioKey) && Database.AudioPaths.ContainsKey(audioKey))
{ {
var audioSourcePath = Database.AudioPaths[audioKey]; var audioSourcePath = Database.AudioPaths[audioKey];
@@ -65,10 +69,40 @@ public class Exporter
File.Copy(audioSourcePath, Path.Combine(exportSongPath, audioExportFileName), true); File.Copy(audioSourcePath, Path.Combine(exportSongPath, audioExportFileName), true);
break; break;
} }
processedAudio.Add(audioKey); finishedAudio.Add(audioKey);
} }
ec.Item1.AudioPath = audioExportFileName; ec.Item1.AudioPath = audioExportFileName;
/// VIDEO ///
// mv_... = set video
// null = use previously set video
// - = disable video
if (!options.ExcludeVideo)
{
var movieProp = song.assetData[Consts.DIFF_MOVIE_KEY[ec.Item1.Difficulty]];
string movie;
if (movieProp.RawValue == null)
movie = prevMovie;
else
movie = movieProp.ToString()!;
if (movie != "-")
{
var vidFileName = $"{movie}.mp4";
if (!finishedMovies.Contains(movie))
{
var vidPath = Path.Combine(Settings.I!.DataPath, "movies", vidFileName);
// TODO: check file's existence to avoid program crash
File.Copy(vidPath, Path.Combine(exportSongPath, vidFileName), true);
finishedMovies.Add(movie);
}
ec.Item1.VideoPath = vidFileName;
}
prevMovie = movie;
}
/// CHART /// /// CHART ///
var chartExt = var chartExt =
options.ChartFormat == FormatVersion.SatV1 || options.ChartFormat == FormatVersion.SatV1 ||
@@ -81,8 +115,7 @@ public class Exporter
ec.Item1, ec.Item2, ec.Item1, ec.Item2,
new NotationWriteArgs { FormatVersion = options.ChartFormat } new NotationWriteArgs { FormatVersion = options.ChartFormat }
); );
// restore audio key in db AFTER exporting metadata
// restore audio key in db AFTER exporting metadata / chart
ec.Item1.AudioPath = audioKey; ec.Item1.AudioPath = audioKey;
} }
+1 -1
View File
@@ -40,7 +40,7 @@
<TextBlock Name="NoFFMpegMessage" Text="Could not find FFmpeg. Make sure it is installed and on PATH!" TextWrapping="Wrap" Foreground="Red" FontWeight="DemiBold" Opacity="0.8" FontSize="12"/> <TextBlock Name="NoFFMpegMessage" Text="Could not find FFmpeg. Make sure it is installed and on PATH!" TextWrapping="Wrap" Foreground="Red" FontWeight="DemiBold" Opacity="0.8" FontSize="12"/>
</StackPanel> </StackPanel>
<CheckBox Name="TickExcludeVideos" Content="Exclude videos" IsChecked="True" IsEnabled="False"/> <CheckBox Name="TickExcludeVideos" Content="Exclude videos"/>
<CheckBox Name="TickGroupExports" Content="Group song folders by release version"/> <CheckBox Name="TickGroupExports" Content="Group song folders by release version"/>
<!-- <CheckBox Content="Delete original files"/> --> <!-- <CheckBox Content="Delete original files"/> -->