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
2 changes: 0 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use clap::{Parser, Subcommand};

use crate::commands::asset::AssetArgs;
use crate::commands::group::GroupArgs;
use crate::commands::upload::UploadArgs;

#[derive(Parser, Debug)]
Expand All @@ -23,7 +22,6 @@ pub struct Cli {
#[derive(Subcommand, Debug)]
pub enum Command {
Asset(AssetArgs),
Group(GroupArgs),
Upload(UploadArgs),
}

Expand Down
60 changes: 0 additions & 60 deletions src/commands/group/list.rs

This file was deleted.

17 changes: 0 additions & 17 deletions src/commands/group/mod.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub mod api_config;
pub mod asset;
pub mod group;
pub mod prompt;
pub mod upload;
54 changes: 40 additions & 14 deletions src/commands/upload/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ fn run_upload(args: UploadCmdArgs) -> Result<(), String> {
}

let mut requests: Vec<AssetUploadRequest> = Vec::with_capacity(files_to_upload.len());
let mut related_umids_per_file: Vec<Vec<String>> = Vec::with_capacity(files_to_upload.len());
let mut file_upload_ids: Vec<String> = Vec::with_capacity(files_to_upload.len());
let mut file_in_app_paths: Vec<String> = Vec::with_capacity(files_to_upload.len());
let mut upload_paths: Vec<PathBuf> = Vec::with_capacity(files_to_upload.len());
Expand Down Expand Up @@ -445,14 +446,18 @@ fn run_upload(args: UploadCmdArgs) -> Result<(), String> {
vec![],
);

if let Some(metadata) = umid {
if let Some(umid_value) = metadata.material_package_umid {
source_info.capture_device_umid = Some(Some(umid_value));
if let Some(metadata) = umid.as_ref() {
if let Some(umid_value) = metadata.material_package_umid.as_ref() {
source_info.capture_device_umid = Some(Some(umid_value.clone()));
}
if let Some(first_umid) = metadata.file_package_umids.first() {
source_info.umid = Some(Some(first_umid.clone()));
if let Some(first_with_data) = metadata.file_package_umids.iter().find(|u| u.has_data) {
source_info.umid = Some(Some(first_with_data.umid.clone()));
}
}
related_umids_per_file.push(
umid.map(|m| m.file_package_umids.iter().map(|u| u.umid.clone()).collect())
.unwrap_or_default(),
);

let req = AssetUploadRequest::new(
i32::try_from(content_length).unwrap_or(i32::MAX),
Expand Down Expand Up @@ -515,6 +520,13 @@ fn run_upload(args: UploadCmdArgs) -> Result<(), String> {
);
preproc_req.generate_time_based_media_description =
Some(!args.disable_description_generation);
let all_related_umids: Vec<String> = related_umids_per_file
.into_iter()
.flat_map(|v| v.into_iter())
.collect();
if !all_related_umids.is_empty() {
preproc_req.related_umid_for_master_clip = Some(Some(all_related_umids));
}
let _ = progress_handle.add_info(format!(
"Triggering preprocessing for {} asset(s)...",
preproc_req.assets.len()
Expand Down Expand Up @@ -744,6 +756,7 @@ fn run_two_queue_pipeline(

let consumer = async move {
let mut completed_responses: Vec<AssetUploadResponse> = Vec::new();
let mut completed_related_umids: Vec<Vec<String>> = Vec::new();
while let Some(file_info) = upload_rx.recv().await {
progress_handle.decrement_upload_queued();
progress_handle.pop_upload_pending();
Expand All @@ -755,11 +768,12 @@ fn run_two_queue_pipeline(
.to_string();
progress_handle.set_upload_current(Some(file_name.clone()));

let (req, _upload_id, in_app_path_str) = build_single_upload_request(
&file_info,
&base_dir_async,
&in_app_path,
)?;
let (req, _upload_id, in_app_path_str, file_related_umids) =
build_single_upload_request(
&file_info,
&base_dir_async,
&in_app_path,
)?;
let responses =
request_presigned_urls(&cfg, &vec![req], &api_key, bearer_header).await?;
let upload_resp = responses
Expand Down Expand Up @@ -799,6 +813,7 @@ fn run_two_queue_pipeline(
));
}
completed_responses.push(upload_resp);
completed_related_umids.push(file_related_umids);
progress_handle.set_upload_current(None::<&str>);
progress_handle.set_upload_current_pct(None);
}
Expand All @@ -810,6 +825,13 @@ fn run_two_queue_pipeline(
);
preproc_req.generate_time_based_media_description =
Some(!disable_description_generation);
let all_related_umids: Vec<String> = completed_related_umids
.iter()
.flat_map(|v| v.iter().cloned())
.collect();
if !all_related_umids.is_empty() {
preproc_req.related_umid_for_master_clip = Some(Some(all_related_umids));
}
let _ = progress_handle.add_info("Triggering preprocessing...");
let preproc_tasks = api::process_assets_users_assets_preprocess_post(
&cfg,
Expand Down Expand Up @@ -847,7 +869,7 @@ fn build_single_upload_request(
file_info: &FileToUpload,
base_dir: &PathBuf,
in_app_path: &Option<String>,
) -> Result<(AssetUploadRequest, String, String), String> {
) -> Result<(AssetUploadRequest, String, String, Vec<String>), String> {
let content_length = std::fs::metadata(&file_info.upload_path)
.map_err(|e| format!("failed to stat {}: {}", file_info.upload_path.display(), e))?
.len();
Expand Down Expand Up @@ -877,20 +899,24 @@ fn build_single_upload_request(
None,
vec![],
);
let related_umids: Vec<String> = umid
.as_ref()
.map(|m| m.file_package_umids.iter().map(|u| u.umid.clone()).collect())
.unwrap_or_default();
if let Some(metadata) = umid {
if let Some(umid_value) = metadata.material_package_umid {
source_info.capture_device_umid = Some(Some(umid_value));
}
if let Some(first_umid) = metadata.file_package_umids.first() {
source_info.umid = Some(Some(first_umid.clone()));
if let Some(first_with_data) = metadata.file_package_umids.iter().find(|u| u.has_data) {
source_info.umid = Some(Some(first_with_data.umid.clone()));
}
}
let req = AssetUploadRequest::new(
i32::try_from(content_length).unwrap_or(i32::MAX),
upload_id.clone(),
source_info,
);
Ok((req, upload_id, file_in_app_path))
Ok((req, upload_id, file_in_app_path, related_umids))
}

async fn request_presigned_urls(
Expand Down
10 changes: 0 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ fn main() {
}
}
}
Some(cli::Command::Group(group_args)) => {
match group_args.command {
commands::group::GroupCommand::List(list_args) => {
if let Err(error) = commands::group::list_run(list_args) {
eprintln!("error: {}", error);
std::process::exit(1);
}
}
}
}
Some(cli::Command::Upload(upload_args)) => {
if let Err(error) = commands::upload::run(upload_args) {
eprintln!("error: {}", error);
Expand Down
40 changes: 25 additions & 15 deletions src/media/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@ use std::path::PathBuf;
use std::process::Command;
use std::sync::OnceLock;

/// A file-package UMID with a flag indicating whether the stream has media data.
#[derive(Clone, Debug)]
pub struct FilePackageUmid {
pub umid: String,
/// True if this UMID came from a stream with actual media data (video/audio);
/// false if from a stream with `codec_type == "data"` (no media data in the stream).
pub has_data: bool,
}

pub struct MediaMetadata {
pub material_package_umid: Option<String>,
pub file_package_umids: Vec<String>,
pub file_package_umids: Vec<FilePackageUmid>,
}

pub fn extract_media_metadata(path: &PathBuf) -> Result<MediaMetadata, String> {
Expand All @@ -21,7 +30,7 @@ pub fn extract_media_metadata(path: &PathBuf) -> Result<MediaMetadata, String> {
#[derive(Debug, Default)]
pub struct MxfUmids {
pub material_package_umid: Option<String>,
pub file_package_umids: Vec<String>,
pub file_package_umids: Vec<FilePackageUmid>,
}

fn run_ffprobe_json(path: &PathBuf) -> Result<Option<Value>, String> {
Expand Down Expand Up @@ -98,7 +107,7 @@ fn extract_mxf_umids(path: &PathBuf) -> Result<MxfUmids, String> {
};

let mut material = None;
let mut file_package_ids: Vec<String> = Vec::new();
let mut file_package_ids: Vec<FilePackageUmid> = Vec::new();

if let Some(format) = payload.get("format") {
if let Some(tags) = format.get("tags") {
Expand All @@ -113,22 +122,23 @@ fn extract_mxf_umids(path: &PathBuf) -> Result<MxfUmids, String> {
if let Some(streams) = payload.get("streams") {
if let Some(streams_array) = streams.as_array() {
for stream in streams_array {
// Skip streams with codec_type "data"
// codec_type == "data" means that there is no data in the stream
if let Some(codec_type) = stream.get("codec_type") {
if let Some(codec_type_str) = codec_type.as_str() {
if codec_type_str == "data" {
continue;
}
}
}

// Collect file_package_umid from all streams (including codec_type "data")
// so they can be sent as related_umid_for_master_clip. Record whether
// the stream has media data (video/audio) or is data-only (codec_type "data").
let has_data = stream
.get("codec_type")
.and_then(|v| v.as_str())
.map(|s| s != "data")
.unwrap_or(true);
if let Some(tags) = stream.get("tags") {
if let Some(tags_obj) = tags.as_object() {
if let Some(umid_value) = tags_obj.get("file_package_umid") {
if let Some(file_umid) = sanitize_umid(umid_value.as_str()) {
if !file_package_ids.contains(&file_umid) {
file_package_ids.push(file_umid);
if !file_package_ids.iter().any(|u| u.umid == file_umid) {
file_package_ids.push(FilePackageUmid {
umid: file_umid,
has_data,
});
}
}
}
Expand Down
Loading