encode command

This commit is contained in:
2026-03-11 07:53:06 -07:00
parent e83d0e5ff9
commit 4fe2eed922
2 changed files with 125 additions and 16 deletions

View File

@@ -1,9 +1,104 @@
use std::io::Write;
use std::num::NonZeroU32;
use std::path::PathBuf;
use strafesnet_common::session::Time as SessionTime;
pub fn main(){
#[derive(clap::Subcommand)]
pub enum Commands{
Encode(EncodeSubcommand),
}
impl Commands{
pub fn run(self){
match self{
Commands::Encode(command)=>command.run().unwrap(),
}
}
}
#[derive(clap::Args)]
pub struct EncodeSubcommand{
#[arg(long,short)]
map:PathBuf,
#[arg(long,short)]
bot:PathBuf,
#[arg(long,short)]
output_file:Option<PathBuf>,
#[arg(long,short)]
width:Option<NonZeroU32>,
#[arg(long,short)]
height:Option<NonZeroU32>,
#[arg(long)]
fps:Option<u32>,
#[arg(long)]
target_bitrate:Option<u64>,
#[arg(long)]
max_bitrate:Option<u64>,
#[arg(long)]
device:Option<String>,
}
impl EncodeSubcommand{
fn run(self)->Result<(),EncodeError>{
encode(EncodeParams{
width:self.width.unwrap_or(NonZeroU32::new(1920).unwrap()),
height:self.width.unwrap_or(NonZeroU32::new(1080).unwrap()),
target_framerate:self.fps.unwrap_or(60),
average_bitrate:self.target_bitrate.unwrap_or(6_000_000),
max_bitrate:self.max_bitrate.unwrap_or(6_000_000),
device:self.device,
map:self.map,
bot:self.bot,
})
}
}
#[expect(dead_code)]
#[derive(Debug)]
enum EncodeError{
ReadMap(std::io::Error),
ReadBot(std::io::Error),
DecodeSNF(strafesnet_snf::Error),
DecodeMap(strafesnet_snf::map::Error),
DecodeBot(strafesnet_roblox_bot_file::v0::Error),
}
struct EncodeParams{
width:NonZeroU32,
height:NonZeroU32,
target_framerate:u32,
average_bitrate:u64,
max_bitrate:u64,
device:Option<String>,
map:PathBuf,
bot:PathBuf,
}
fn encode(params:EncodeParams)->Result<(),EncodeError>{
let size = glam::uvec2(params.width.get(),params.height.get());
let target_framerate = params.target_framerate;
let average_bitrate = params.average_bitrate;
let max_bitrate = params.max_bitrate;
let map_file=std::fs::read(params.map).map_err(EncodeError::ReadMap)?;
let bot_file=std::fs::read(params.bot).map_err(EncodeError::ReadBot)?;
// read files
let map=strafesnet_snf::read_map(std::io::Cursor::new(map_file))
.map_err(EncodeError::DecodeSNF)?
.into_complete_map()
.map_err(EncodeError::DecodeMap)?;
let timelines=strafesnet_roblox_bot_file::v0::read_all_to_block(std::io::Cursor::new(bot_file))
.map_err(EncodeError::DecodeBot)?;
let vulkan_instance = vk_video::VulkanInstance::new().unwrap();
let vulkan_adapter = vulkan_instance.create_adapter(None).unwrap();
let vulkan_adapter = if let Some(filter)=params.device.as_deref(){
vulkan_instance.iter_adapters(None)
.unwrap()
.find(|adapter|adapter.info().name.contains(filter))
.unwrap()
}else{
vulkan_instance.create_adapter(None).unwrap()
};
let vulkan_device = vulkan_adapter
.create_device(
wgpu::Features::TEXTURE_COMPRESSION_BC,
@@ -12,18 +107,6 @@ pub fn main(){
)
.unwrap();
let size = glam::uvec2(1920,1080);
let target_framerate = 60;
let average_bitrate = 10_000_000;
let max_bitrate = 20_000_000;
let bot_file=include_bytes!("../../web-demo/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d.qbot");
let map_file=include_bytes!("../../web-demo/bhop_marble_5692093612.snfm");
// decode
let timelines=strafesnet_roblox_bot_file::v0::read_all_to_block(std::io::Cursor::new(bot_file)).unwrap();
let map=strafesnet_snf::read_map(std::io::Cursor::new(map_file)).unwrap().into_complete_map().unwrap();
// playback
let bot=strafesnet_roblox_bot_player::bot::CompleteBot::new(timelines);
let mut playback_head=strafesnet_roblox_bot_player::head::PlaybackHead::new(&bot,SessionTime::ZERO);
@@ -41,8 +124,8 @@ pub fn main(){
vulkan_device
.encoder_parameters_high_quality(
vk_video::parameters::VideoParameters {
width:size.x.try_into().unwrap(),
height:size.y.try_into().unwrap(),
width:params.width,
height:params.height,
target_framerate:target_framerate.into(),
},
vk_video::parameters::RateControl::VariableBitrate {
@@ -78,6 +161,8 @@ pub fn main(){
output_file.write_all(&res.data).unwrap();
}
Ok(())
}
struct WgpuState {

24
video-encoder/src/main.rs Normal file
View File

@@ -0,0 +1,24 @@
use clap::{Parser,Subcommand};
mod encode;
#[derive(Parser)]
#[command(author,version,about,long_about=None)]
#[command(propagate_version=true)]
struct Cli{
#[command(subcommand)]
command:Commands,
}
#[derive(Subcommand)]
enum Commands{
#[command(flatten)]
Encode(encode::Commands),
}
fn main(){
let cli=Cli::parse();
match cli.command{
Commands::Encode(commands)=>commands.run(),
}
}