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
1 change: 0 additions & 1 deletion scripts/generate_api.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ elif [ -f "${ROOT_DIR}/openapi-generator-cli.jar" ]; then
GENERATOR="java -jar ${ROOT_DIR}/openapi-generator-cli.jar"
else
echo "OpenAPI Generator not found. We use openapi-generator-cli 7.17.0. Install with version control:"
echo " - brew: brew install openapi-generator@7.17"
echo " - npm: npm i -g @openapitools/openapi-generator-cli"
exit 1
fi
Expand Down
28 changes: 22 additions & 6 deletions src/commands/upload/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use walkdir::WalkDir;
use crate::auth;
use crate::commands::api_config;
use crate::media::ffmpeg::ensure_ffmpeg_available;
use crate::media::metadata::extract_media_metadata;
use crate::media::metadata::{extract_media_metadata, get_ffprobe_json};
use crate::media::media_file_type::is_audio_file;
use crate::media::transcode::{
convert_to_mp3, create_rendition, has_video_streams, is_mxf_file, normalize_audio_to_mp3,
Expand Down Expand Up @@ -224,7 +224,8 @@ fn run_recreate_filesystem(args: RecreateFilesystemArgs) -> Result<(), String> {
.map_err(|e| format!("failed to start runtime: {}", e))?;

for folder_path in in_app_paths {
let req = CreateFolderRequest::new(folder_path.clone());
let mut req = CreateFolderRequest::new();
req.path = Some(Some(folder_path.clone()));
let response = rt.block_on(api::create_folder_asset_folder_post(
&cfg,
req,
Expand Down Expand Up @@ -455,6 +456,14 @@ fn run_upload(args: UploadCmdArgs) -> Result<(), String> {
source_info.umid = Some(Some(first_with_data.umid.clone()));
}
}
if is_mxf_file(&file_info.original_path) {
if let Ok(Some(probe)) = get_ffprobe_json(&file_info.original_path) {
if let serde_json::Value::Object(map) = probe {
source_info.original_ffprobe_metadata =
Some(Some(map.into_iter().collect()));
}
}
}
related_umids_per_file.push(
umid.map(|m| m.file_package_umids.iter().map(|u| u.umid.clone()).collect())
.unwrap_or_default(),
Expand Down Expand Up @@ -791,9 +800,9 @@ fn run_two_queue_pipeline(
);
preproc_req.generate_time_based_media_description =
Some(!disable_description_generation);
// related_umid_for_master_clip removed in current API; use override_entity_ids if needed
if !file_related_umids.is_empty() {
preproc_req.related_umid_for_master_clip =
Some(Some(file_related_umids));
preproc_req.override_entity_ids = Some(Some(file_related_umids));
}
let preproc_tasks = api::process_assets_users_assets_preprocess_post(
&cfg,
Expand Down Expand Up @@ -876,6 +885,14 @@ fn build_single_upload_request(
source_info.umid = Some(Some(first_with_data.umid.clone()));
}
}
if is_mxf_file(&file_info.original_path) {
if let Ok(Some(probe)) = get_ffprobe_json(&file_info.original_path) {
if let serde_json::Value::Object(map) = probe {
source_info.original_ffprobe_metadata =
Some(Some(map.into_iter().collect()));
}
}
}
let req = AssetUploadRequest::new(
i32::try_from(content_length).unwrap_or(i32::MAX),
upload_id.clone(),
Expand Down Expand Up @@ -1050,8 +1067,7 @@ async fn upload_to_presigned_urls(
preproc_req.generate_time_based_media_description =
Some(!disable_description_generation);
if !file_related_umids.is_empty() {
preproc_req.related_umid_for_master_clip =
Some(Some(file_related_umids));
preproc_req.override_entity_ids = Some(Some(file_related_umids));
}
if let Err(e) = api::process_assets_users_assets_preprocess_post(
&cfg_clone,
Expand Down
12 changes: 9 additions & 3 deletions src/media/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ pub fn extract_media_metadata(path: &PathBuf) -> Result<MediaMetadata, String> {
})
}

/// Returns raw ffprobe JSON (format + streams) for the given file, or None if ffprobe fails.
pub fn get_ffprobe_json(path: &PathBuf) -> Result<Option<Value>, String> {
run_ffprobe_json(path)
}

#[derive(Debug, Default)]
pub struct MxfUmids {
pub material_package_umid: Option<String>,
Expand All @@ -37,11 +42,12 @@ fn run_ffprobe_json(path: &PathBuf) -> Result<Option<Value>, String> {
let output = Command::new("ffprobe")
.args([
"-v",
"error",
"quiet",
"-count_frames",
"-print_format",
"json",
"-show_format",
"-show_streams",
"-of",
"json",
&path.to_string_lossy(),
])
.output()
Expand Down
74 changes: 61 additions & 13 deletions src/tellers_api/openapi.tellers_public_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,12 @@ paths:
Uses default group(s) unless group_id is set (user must have read access to
that group).

after: only files with last_edit > after (newer).

before: only files with last_edit < before (older); use the smallest last_edit
from a previous page to get the next page.'
from a previous page to get the next page.

filetype: only files with the given file type(s).'
operationId: get_most_recent_files_asset_most_recent_get
parameters:
- name: path
Expand Down Expand Up @@ -354,6 +358,15 @@ paths:
format: date-time
- type: 'null'
title: Before
- name: after
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: After
- name: x-api-key
in: header
required: false
Expand All @@ -370,6 +383,16 @@ paths:
- type: string
- type: 'null'
title: Authorization
requestBody:
content:
application/json:
schema:
anyOf:
- type: array
items:
$ref: '#/components/schemas/FileType'
- type: 'null'
title: Filetype
responses:
'200':
description: Successful Response
Expand All @@ -391,8 +414,12 @@ paths:
tags:
- accepts-api-key
summary: Create Folder
description: 'Create a folder at the given path. Ensures the folder and all
ancestor folders exist for the user''s default group.
description: 'Create a folder. Either at a path (body.path) or under a parent
folder (body.parent_asset_id + body.name).

Path-based: ensures folder and ancestors exist for the user''s default group.

Parent-based: parent must be a folder the user has WRITE access to.

Callable with API key (X-Api-Key header) or Bearer token.'
operationId: create_folder_asset_folder_post
Expand Down Expand Up @@ -1185,19 +1212,35 @@ components:
CreateFolderRequest:
properties:
path:
type: string
anyOf:
- type: string
- type: 'null'
title: Path
parent_asset_id:
anyOf:
- type: string
- type: 'null'
title: Parent Asset Id
name:
anyOf:
- type: string
- type: 'null'
title: Name
type: object
required:
- path
title: CreateFolderRequest
description: Either provide path (create at path) or parent_asset_id + name
(create under parent).
CreateFolderResponse:
properties:
id:
type: string
title: Id
path:
type: string
title: Path
type: object
required:
- id
- path
title: CreateFolderResponse
FileReference:
Expand Down Expand Up @@ -1243,6 +1286,7 @@ components:
- image
- placeholder
- group_clip
- aaf
- folder
- project
- entity
Expand Down Expand Up @@ -1328,13 +1372,6 @@ components:
type: array
- type: 'null'
title: Override Entity Ids
related_umid_for_master_clip:
anyOf:
- items:
type: string
type: array
- type: 'null'
title: Related Umid For Master Clip
type: object
required:
- assets
Expand Down Expand Up @@ -1443,6 +1480,17 @@ components:
- type: string
- type: 'null'
title: Capture Device Umid
original_file_path:
anyOf:
- type: string
- type: 'null'
title: Original File Path
original_ffprobe_metadata:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Original Ffprobe Metadata
type: object
required:
- sourceName
Expand Down