feat(api): add GET /assets/:id/hires endpoint for original file download

Returns presigned S3 URL + filename/ext/file_size for the original
hi-res source so the Premiere plugin can download and import it.
This commit is contained in:
Zac Gaetano 2026-05-20 00:34:18 -04:00
parent f7aedb1936
commit a855ea7885

View file

@ -434,7 +434,7 @@ router.delete('/:id', async (req, res, next) => {
} }
}); });
// GET /:id/stream - Signed URL for proxy playback // GET /:id/stream - URL for proxy playback (relative path, for browser use)
router.get('/:id/stream', async (req, res, next) => { router.get('/:id/stream', async (req, res, next) => {
try { try {
const { id } = req.params; const { id } = req.params;
@ -483,6 +483,31 @@ router.get('/:id/video', async (req, res, next) => {
} catch (err) { next(err); } } catch (err) { next(err); }
}); });
// GET /:id/hires - Presigned S3 URL for the original hi-res source file
//
// Returns a short-lived presigned URL that the Premiere plugin can use to
// download the full-resolution original directly from S3. Also includes
// the derived filename and file_size so the client can show a size warning.
router.get('/:id/hires', async (req, res, next) => {
try {
const { id } = req.params;
const r = await pool.query(
'SELECT original_s3_key, filename, display_name, file_size FROM assets WHERE id = $1',
[id]
);
if (r.rows.length === 0) return res.status(404).json({ error: 'Asset not found' });
const a = r.rows[0];
if (!a.original_s3_key) {
return res.status(404).json({ error: 'No hi-res source available for this asset' });
}
const url = await getSignedUrlForObject(a.original_s3_key);
const parts = a.original_s3_key.split('.');
const ext = (parts.length > 1 ? parts[parts.length - 1] : 'mxf').toLowerCase();
const base = (a.display_name || a.filename || id).replace(/[^\w.-]/g, '_').substring(0, 100);
res.json({ url, filename: `${base}.${ext}`, ext, file_size: a.file_size || null, type: 'hires' });
} catch (err) { next(err); }
});
// GET /:id/thumbnail - Signed URL (JSON) or 302 redirect (?redirect=1) for thumbnail // GET /:id/thumbnail - Signed URL (JSON) or 302 redirect (?redirect=1) for thumbnail
router.get('/:id/thumbnail', async (req, res, next) => { router.get('/:id/thumbnail', async (req, res, next) => {
try { try {