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
12 changes: 10 additions & 2 deletions src/exportHandler/exportHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export interface ExportOptions {
removeIds?: boolean;
includeAudio?: boolean;
includeTimestamps?: boolean;
excludeLabels?: boolean;
/** Per-file 0-based milestone indices to include when exporting audio. An empty array skips that file entirely. Files omitted from this map are exported in full (no milestone step). */
selectedMilestonesByFile?: Record<string, number[]>;
}
Expand Down Expand Up @@ -2066,8 +2067,15 @@ export const exportCodexContentAsSubtitlesVtt = async (
totalCells += cells.length;
debug(`File has ${cells.length} active cells`);

const vttContent = generateVttData(cells, includeStyles, cueSplitting, file.fsPath);
debug({ vttContent, cells, includeStyles });
// Generate VTT content
const vttContent = generateVttData(
cells,
includeStyles,
cueSplitting,
file.fsPath,
options?.excludeLabels === true
);
debug({ vttContent, cells, includeStyles });

const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
const fileName = basename(file.fsPath).replace(".codex", "") || "unknown";
Expand Down
5 changes: 3 additions & 2 deletions src/exportHandler/vttUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ export const generateVttData = (
cells: CodexNotebookAsJSONData["cells"],
includeStyles: boolean,
cueSplitting: boolean,
filePath: string
filePath: string,
excludeLabels: boolean = false
): string => {
if (!cells.length) return "";

Expand All @@ -95,7 +96,7 @@ export const generateVttData = (
const text = includeStyles ? processVttContent(unit.value) : removeHtmlTags(unit.value);
const finalText = ensureDialogueLineBreaks(text);

const rawLabel = unit.metadata?.cellLabel?.trim();
const rawLabel = excludeLabels ? undefined : unit.metadata?.cellLabel?.trim();
const payload = rawLabel
? `<v ${escapeVoiceName(rawLabel)}>${finalText}</v>`
: finalText;
Expand Down
9 changes: 9 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,15 @@ export async function activate(context: vscode.ExtensionContext) {

initToolPreferences(context);

// Clear the stream-only video session cache (stored outside the project) so
// "Loaded" videos re-stream after a reload, like the in-memory audio cache.
try {
const { clearVideoStreamCache } = await import("./utils/videoStreamCache");
await clearVideoStreamCache(context);
} catch (e) {
console.warn("[Extension] Could not clear video stream cache:", e);
}

// Per-user audio preferences (autoDownloadAudioOnOpen,
// autoRecordOnMicClick, recordingCountdownSeconds) live in globalState.
// Initialize before any provider reads them; the per-workspace migration
Expand Down
25 changes: 25 additions & 0 deletions src/projectManager/projectExportView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,21 @@ function getWebviewContent(
.format-option-row[data-option].hidden { display: none !important; }
.format-option p, .format-option-content p { line-height: 1.45; margin: 4px 0 0 0; }
.format-option-content { display: flex; flex-direction: column; gap: 4px; }
.format-option-toggle {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.9em;
color: var(--vscode-descriptionForeground);
cursor: pointer;
user-select: none;
}
.format-option-toggle input[type="checkbox"] { margin: 0; cursor: pointer; }
.format-section-suboption {
padding: 10px 12px;
background-color: var(--vscode-editor-background);
border-top: 1px solid var(--vscode-input-border);
}
.format-tag {
display: inline-block;
padding: 1px 4px;
Expand Down Expand Up @@ -1248,6 +1263,12 @@ function getWebviewContent(
</div>
</div>
</div>
<div class="format-section-suboption">
<label class="format-option-toggle" id="vttExcludeLabelsToggle">
<input type="checkbox" id="vttExcludeLabelsCb">
Exclude speaker labels from WebVTT cues
</label>
</div>
</div>
<!-- Round-trip: only for supported file types -->
<div class="roundtrip-wrapper" data-option="roundTrip">
Expand Down Expand Up @@ -2954,6 +2975,10 @@ function getWebviewContent(
options.includeAudio = true;
options.includeTimestamps = selectedAudioMode === 'audio-timestamps';
}
if (selectedFormat && selectedFormat.startsWith('subtitles-vtt-')) {
const cb = document.getElementById('vttExcludeLabelsCb');
if (cb && cb.checked) options.excludeLabels = true;
}
const selectedMilestones = buildSelectedMilestonesPayload();
if (selectedMilestones) {
options.selectedMilestonesByFile = selectedMilestones;
Expand Down
18 changes: 18 additions & 0 deletions src/projectManager/syncManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,19 @@ export class SyncManager {
// Don't fail sync completion due to cleanup errors
}

// Refresh the chapter video reference status in open editors so a video
// just uploaded to LFS this sync now offers the "Free up space" action.
try {
const { GlobalProvider } = await import("../globalProvider");
const provider = GlobalProvider.getInstance().getProvider("codex-cell-editor") as any;
if (provider && typeof provider.refreshVideoReferenceStatusAfterSync === "function") {
await provider.refreshVideoReferenceStatusAfterSync();
}
} catch (error) {
console.error("[SyncManager] Error refreshing video reference status after sync:", error);
// Don't fail sync completion due to video status refresh errors
}

// Update sync stage and splash screen
this.currentSyncStage = "Sync complete!";
this.notifySyncStatusListeners();
Expand Down Expand Up @@ -1682,6 +1695,11 @@ export class SyncManager {
return 'Uploading changes...';
}
if (stage.includes('Uploading media')) {
// Surface connection/retry detail verbatim so the user
// can see what's happening (e.g. "retrying in 9s").
if (/retry|retrying|waiting|interrupted|stalled|connection/i.test(stage)) {
return stage;
}
const pctMatch = stage.match(/(\d+)%/);
if (pctMatch) {
return `Uploading media... ${pctMatch[1]}%`;
Expand Down
Loading
Loading