Skip to content

Commit f44c2fc

Browse files
committed
v1.9.34: transcript-to-timeline scrubber (feature H)
Click any transcript segment (either the editable row or the timeline chip) and OpenCut now moves the active Premiere sequence's playhead to that segment's start time. Descript-style navigation on top of the existing transcript editor. - host/index.jsx: new ocSetSequencePlayhead(seconds) — tries the tick-string signature first (modern Premiere), then numeric, then a Time-object fallback. ES3-compliant. Quiet error return if the active build rejects all three. - main.js: PremiereBridge.setPlayhead wrapper, _jumpPlayheadToSegment helper, wired into the existing transcript-segments and transcript-timeline click handlers. First-failure toast, silent after that so repeated clicks don't spam the panel.
1 parent 369d911 commit f44c2fc

18 files changed

Lines changed: 95 additions & 20 deletions

File tree

Install.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ Write-Host " \___/| .__/ \___|_| |_|\____\__,_|\__|" -ForegroundColor Cyan
155155
Write-Host " |_| " -ForegroundColor Cyan
156156
Write-Host ""
157157
Write-Host " Open Source Video Editing Automation" -ForegroundColor DarkGray
158-
Write-Host " Installer v1.9.33" -ForegroundColor DarkGray
158+
Write-Host " Installer v1.9.34" -ForegroundColor DarkGray
159159

160160
$isAdmin = Test-IsAdmin
161161
if ($isAdmin) {

OpenCut.iss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; Fully self-contained installer — bundles server exe, ffmpeg, and CEP extension
33

44
#define MyAppName "OpenCut"
5-
#define MyAppVersion "1.9.33"
5+
#define MyAppVersion "1.9.34"
66
#define MyAppPublisher "SysAdminDoc"
77
#define MyAppURL "https://github.com/SysAdminDoc/OpenCut"
88

extension/com.opencut.panel/CSXS/manifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<ExtensionManifest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
33
Version="7.0"
44
ExtensionBundleId="com.opencut.panel"
5-
ExtensionBundleVersion="1.9.33"
5+
ExtensionBundleVersion="1.9.34"
66
ExtensionBundleName="OpenCut">
77

88
<ExtensionList>
9-
<Extension Id="com.opencut.panel.main" Version="1.9.33" />
9+
<Extension Id="com.opencut.panel.main" Version="1.9.34" />
1010
</ExtensionList>
1111

1212
<ExecutionEnvironment>

extension/com.opencut.panel/client/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3597,7 +3597,7 @@ <h3 class="media-sidecar-title">No media in the workspace yet.</h3>
35973597
<div class="card-header"><div class="card-title" data-i18n="settings.about">About OpenCut</div></div>
35983598
<div class="settings-row">
35993599
<span class="settings-label">Version</span>
3600-
<span class="settings-value">1.9.33</span>
3600+
<span class="settings-value">1.9.34</span>
36013601
</div>
36023602
<div class="about-links">
36033603
<a href="https://github.com/SysAdminDoc/opencut" class="about-link" target="_blank">GitHub</a>

extension/com.opencut.panel/client/main.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* ============================================================
2-
OpenCut CEP Panel - Main Controller v1.9.33
2+
OpenCut CEP Panel - Main Controller v1.9.34
33
6-Tab Professional Toolkit
44
============================================================ */
55
(function () {
@@ -1386,6 +1386,9 @@
13861386
removeImportedItem: function (payload, cb) {
13871387
var json = JSON.stringify(payload);
13881388
jsx("ocRemoveImportedItem('" + json.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "')", cb);
1389+
},
1390+
setPlayhead: function (seconds, cb) {
1391+
jsx("ocSetSequencePlayhead(" + Number(seconds || 0) + ")", cb);
13891392
}
13901393
};
13911394

@@ -5005,6 +5008,30 @@
50055008
return transcriptData && transcriptData.segments ? transcriptData.segments : [];
50065009
}
50075010

5011+
// v1.9.34 (H): jump the Premiere playhead to a transcript segment's
5012+
// start time. Quiet no-op outside Premiere so dev-mode use stays clean.
5013+
function _jumpPlayheadToSegment(idx) {
5014+
if (!inPremiere) return;
5015+
var segs = getTranscriptSegments();
5016+
if (!segs || idx < 0 || idx >= segs.length) return;
5017+
var t = Number(segs[idx].start || 0);
5018+
if (!isFinite(t) || t < 0) return;
5019+
PremiereBridge.setPlayhead(t, function (result) {
5020+
// Only warn on errors if the first click fails; subsequent
5021+
// ones stay quiet to avoid spamming toasts on every tap.
5022+
if (!_playheadSyncWarned && result && result.indexOf("error") !== -1) {
5023+
try {
5024+
var r = JSON.parse(result);
5025+
if (r && r.error) {
5026+
_playheadSyncWarned = true;
5027+
showToast("Playhead sync unavailable: " + r.error, "warn");
5028+
}
5029+
} catch (e) {}
5030+
}
5031+
});
5032+
}
5033+
var _playheadSyncWarned = false;
5034+
50085035
function getTranscriptTotalDuration(data) {
50095036
var segments = data && data.segments ? data.segments : [];
50105037
var maxEnd = 0;
@@ -5323,6 +5350,9 @@
53235350
var idx = parseInt(row.getAttribute("data-idx"), 10);
53245351
if (!(idx >= 0)) return;
53255352
focusTranscriptSegment(idx, { scroll: false, scrollTimeline: true });
5353+
// v1.9.34 (H): jump the Premiere playhead to this segment's
5354+
// start time. Silently no-op when outside Premiere.
5355+
_jumpPlayheadToSegment(idx);
53265356
if (!e.target.classList.contains("transcript-seg-text")) {
53275357
var ta = row.querySelector(".transcript-seg-text");
53285358
if (ta) ta.focus();
@@ -5339,7 +5369,10 @@
53395369
var btn = e.target.closest(".transcript-timeline-seg");
53405370
if (!btn) return;
53415371
var idx = parseInt(btn.getAttribute("data-idx"), 10);
5342-
if (idx >= 0) focusTranscriptSegment(idx, { focusInput: true });
5372+
if (idx >= 0) {
5373+
focusTranscriptSegment(idx, { focusInput: true });
5374+
_jumpPlayheadToSegment(idx);
5375+
}
53435376
});
53445377
el.transcriptTimeline.addEventListener("keydown", function (e) {
53455378
var btn = e.target.closest(".transcript-timeline-seg");

extension/com.opencut.panel/client/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* ============================================================
2-
OpenCut CEP Panel v1.9.33 - ULTRA PREMIUM EDITION
2+
OpenCut CEP Panel v1.9.34 - ULTRA PREMIUM EDITION
33
Next-Generation AI Editing Suite for Adobe Premiere Pro
44
============================================================ */
55

extension/com.opencut.panel/host/index.jsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,48 @@ function ocRemoveImportedSequence(payloadJSON) {
24582458
}
24592459
}
24602460

2461+
// v1.9.34 (H) — Move the active sequence's playhead to *seconds*. One-arg
2462+
// form for simpler panel invocation. Uses ticks (254016000000 per second)
2463+
// when setPlayerPosition expects a tick string, or falls back to seconds.
2464+
function ocSetSequencePlayhead(seconds) {
2465+
try {
2466+
if (!app || !app.project || !app.project.activeSequence) {
2467+
return JSON.stringify({ error: "No active sequence" });
2468+
}
2469+
var secs = Number(seconds);
2470+
if (!isFinite(secs) || secs < 0) {
2471+
return JSON.stringify({ error: "Invalid seconds" });
2472+
}
2473+
var seq = app.project.activeSequence;
2474+
2475+
// Try the modern setPlayerPosition(ticks_as_string) signature first.
2476+
var ticks = Math.floor(secs * 254016000000);
2477+
try {
2478+
seq.setPlayerPosition(ticks.toString());
2479+
return JSON.stringify({ success: true, seconds: secs });
2480+
} catch (e1) {}
2481+
2482+
// Fallback: some Premiere builds accept a Number
2483+
try {
2484+
seq.setPlayerPosition(ticks);
2485+
return JSON.stringify({ success: true, seconds: secs });
2486+
} catch (e2) {}
2487+
2488+
// Last resort: cursor via Time object
2489+
try {
2490+
var t = {};
2491+
t.ticks = ticks.toString();
2492+
seq.setPlayerPosition(t);
2493+
return JSON.stringify({ success: true, seconds: secs });
2494+
} catch (e3) {
2495+
return JSON.stringify({ error: "setPlayerPosition failed on this Premiere version" });
2496+
}
2497+
} catch (e) {
2498+
_ocLog("ocSetSequencePlayhead error: " + e.toString());
2499+
return JSON.stringify({ error: e.toString() });
2500+
}
2501+
}
2502+
24612503
// Remove an imported project item by node id. Payload: {nodeId:"..."}.
24622504
function ocRemoveImportedItem(payloadJSON) {
24632505
try {

extension/com.opencut.panel/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "opencut-panel",
3-
"version": "1.9.33",
3+
"version": "1.9.34",
44
"private": true,
55
"description": "OpenCut CEP Panel for Adobe Premiere Pro",
66
"scripts": {

extension/com.opencut.uxp/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<path d="M4 2.5a3 3 0 00-1.76 5.43L7.33 11l-5.09 3.07A3 3 0 104.8 19.5a3 3 0 001.76-5.43L8.93 12.6 16.5 17V5L8.93 9.4 6.56 7.93A3 3 0 004 2.5z" fill="var(--accent)"/>
1717
</svg>
1818
<span class="oc-logo">OpenCut</span>
19-
<span class="oc-version">v1.9.33</span>
19+
<span class="oc-version">v1.9.34</span>
2020
</div>
2121
<div class="oc-header-right">
2222
<div class="oc-connection" id="connectionStatus" title="Backend connection status">

extension/com.opencut.uxp/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const HEALTH_CHECK_MS = 8000;
2626
const HEALTH_MAX_MS = 60000;
2727
const MEDIA_SCAN_MS = 30000;
2828
const SSE_AVAILABLE = typeof EventSource !== "undefined";
29-
const VERSION = "1.9.33";
29+
const VERSION = "1.9.34";
3030

3131
async function detectBackend() {
3232
// Try ports 5679-5689 like CEP panel does

0 commit comments

Comments
 (0)