diff --git a/client/dive-common/apispec.ts b/client/dive-common/apispec.ts index abac8415a..952032772 100644 --- a/client/dive-common/apispec.ts +++ b/client/dive-common/apispec.ts @@ -9,6 +9,7 @@ import { CustomStyle } from 'vue-media-annotator/StyleManager'; import { AttributeTrackFilter } from 'vue-media-annotator/AttributeTrackFilterControls'; type DatasetType = 'image-sequence' | 'video' | 'multi' | 'large-image'; +type DiskOpenType = DatasetType | 'bulk' | 'calibration' | 'annotation' | 'camera' | 'text' | 'zip'; type MultiTrackRecord = Record; type MultiGroupRecord = Record; type SubType = 'stereo' | 'multicam' | null; // Additional type info used for UI display enabled pipelines @@ -161,7 +162,7 @@ interface Api { saveAttributeTrackFilters(datasetId: string, args: SaveAttributeTrackFilterArgs): Promise; // Non-Endpoint shared functions - openFromDisk(datasetType: DatasetType | 'bulk' | 'calibration' | 'annotation' | 'text' | 'zip', directory?: boolean): + openFromDisk(datasetType: DiskOpenType, directory?: boolean): Promise<{canceled?: boolean; filePaths: string[]; fileList?: File[]; root?: string}>; getTiles?(itemId: string, projection?: string): Promise; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -197,6 +198,7 @@ export { DatasetMetaMutable, DatasetMetaMutableKeys, DatasetType, + DiskOpenType, SubType, FrameImage, MultiTrackRecord, diff --git a/client/dive-common/components/RunPipelineMenu.vue b/client/dive-common/components/RunPipelineMenu.vue index 61492e772..55a0629cc 100644 --- a/client/dive-common/components/RunPipelineMenu.vue +++ b/client/dive-common/components/RunPipelineMenu.vue @@ -161,6 +161,8 @@ export default defineComponent({ case 'utility': case 'generate': return 'utilities'; + case 'transcode': + return 'transcoders'; default: return `${pipeType}s`; } diff --git a/client/platform/desktop/backend/native/common.ts b/client/platform/desktop/backend/native/common.ts index 858bfa805..7ec3b4e07 100644 --- a/client/platform/desktop/backend/native/common.ts +++ b/client/platform/desktop/backend/native/common.ts @@ -344,7 +344,7 @@ async function autodiscoverData(settings: Settings): Promise { */ async function getPipelineList(settings: Settings): Promise { const pipelinePath = npath.join(settings.viamePath, 'configs/pipelines'); - const allowedPatterns = /^detector_.+|^tracker_.+|^generate_.+|^utility_|^measurement_gmm_.+|.*[2,3]-cam.+/; + const allowedPatterns = /^filter_.+|^transcode_.+|^detector_.+|^tracker_.+|^generate_.+|^utility_|^measurement_gmm_.+|.*[2,3]-cam.+/; const disallowedPatterns = /.*local.*|detector_svm_models.pipe|tracker_svm_models.pipe/; const exists = await fs.pathExists(pipelinePath); if (!exists) return {}; diff --git a/client/platform/desktop/backend/native/viame.ts b/client/platform/desktop/backend/native/viame.ts index 852cd5329..62ab03030 100644 --- a/client/platform/desktop/backend/native/viame.ts +++ b/client/platform/desktop/backend/native/viame.ts @@ -59,7 +59,7 @@ async function runPipeline( //TODO: TEMPORARY FIX FOR DEMO PURPOSES let requiresInput = false; - if ((/utility_/g).test(pipeline.pipe)) { + if ((/utility_|filter_|transcode_/g).test(pipeline.pipe)) { requiresInput = true; } let groundTruthFileName; @@ -126,6 +126,15 @@ async function runPipeline( command.push(`-s track_writer:file_name="${trackOutput}"`); } } + + if (runPipelineArgs.pipeline.type === 'filter') { + command.push(`-s kwa_writer:output_directory="${npath.join(jobWorkDir, 'output')}"`); + command.push(`-s image_writer:file_name_prefix="${jobWorkDir}/"`); + } + if (runPipelineArgs.pipeline.type === 'transcode') { + command.push(`-s video_writer:video_filename="${npath.join(jobWorkDir, `${datasetId}.mp4`)}"`); + } + if (requiresInput && !stereoOrMultiCam) { command.push(`-s detection_reader:file_name="${groundTruthFileName}"`); command.push(`-s track_reader:file_name="${groundTruthFileName}"`); diff --git a/client/platform/desktop/constants.ts b/client/platform/desktop/constants.ts index 282825b57..5c3059efe 100644 --- a/client/platform/desktop/constants.ts +++ b/client/platform/desktop/constants.ts @@ -198,6 +198,7 @@ export interface DesktopMediaImportResponse extends MediaImportResponse { multiCamTrackFiles: null | Record; forceMediaTranscode: boolean; metaFileAbsPath?: string; + cameraFileAbsPath?: string; } export interface DesktopJobUpdate extends DesktopJob { diff --git a/client/platform/desktop/frontend/api.ts b/client/platform/desktop/frontend/api.ts index dc98d2b62..95f3bad92 100644 --- a/client/platform/desktop/frontend/api.ts +++ b/client/platform/desktop/frontend/api.ts @@ -7,7 +7,7 @@ import { ipcRenderer } from 'electron'; import { dialog, app } from '@electron/remote'; import type { - DatasetMetaMutable, DatasetType, MultiCamImportArgs, + DatasetMetaMutable, DiskOpenType, MultiCamImportArgs, Pipe, Pipelines, SaveAttributeArgs, SaveAttributeTrackFilterArgs, SaveDetectionsArgs, TrainingConfigs, } from 'dive-common/apispec'; @@ -26,7 +26,7 @@ import { * Native functions that run entirely in the renderer */ -async function openFromDisk(datasetType: DatasetType | 'bulk' | 'calibration' | 'annotation' | 'text', directory = false) { +async function openFromDisk(datasetType: DiskOpenType, directory = false) { let filters: FileFilter[] = []; const allFiles = { name: 'All Files', extensions: ['*'] }; if (datasetType === 'video') { diff --git a/client/platform/desktop/frontend/components/ImportDialog.vue b/client/platform/desktop/frontend/components/ImportDialog.vue index a7b6882ea..dc139587d 100644 --- a/client/platform/desktop/frontend/components/ImportDialog.vue +++ b/client/platform/desktop/frontend/components/ImportDialog.vue @@ -69,8 +69,12 @@ export default defineComponent({ }); const { openFromDisk } = useApi(); - const openUpload = async (type: 'annotation' | 'meta') => { - const argMap = { annotation: 'trackFileAbsPath', meta: 'metaFileAbsPath' }; + const openUpload = async (type: 'annotation' | 'meta' | 'camera') => { + const argMap = { + annotation: 'trackFileAbsPath', + meta: 'metaFileAbsPath', + camera: 'cameraFileAbsPath', + }; const ret = await openFromDisk('annotation'); if (!ret.canceled) { if (ret.filePaths?.length) { @@ -201,6 +205,24 @@ export default defineComponent({ /> + + + + +