From f469ab7444b0b3b0e80b36af7913223bcb2c6ef7 Mon Sep 17 00:00:00 2001 From: th Date: Sun, 7 Jun 2026 12:10:35 +0200 Subject: [PATCH] Clarify export runtime copy --- src/App.vue | 6 +++- src/components/ExportDialog.vue | 31 +++++++++++----- src/components/HelpDialog.vue | 16 +++++++-- src/i18n/messages.ts | 64 ++++++++++++++++++++++----------- 4 files changed, 85 insertions(+), 32 deletions(-) diff --git a/src/App.vue b/src/App.vue index 4b8387a..a32dfee 100644 --- a/src/App.vue +++ b/src/App.vue @@ -68,6 +68,7 @@ const welcomeOpen = ref(false) const fullscreenOpen = ref(false) const aboutOpen = ref(false) const helpOpen = ref(false) +const isDesktop = computed(() => !!window.ruwioDesktop) const TestOverlay = import.meta.env.DEV ? defineAsyncComponent(() => import('./devtools/TestOverlay.vue')) : null @@ -745,7 +746,10 @@ onBeforeUnmount(() => { - @@ -610,10 +617,16 @@ function onUpdate(v: boolean) {
WebM Video - {{ t('export.webmBadge') }} + + {{ t(isDesktop ? 'export.webmDesktopBadge' : 'export.webmBrowserBadge') }} +
- {{ videoSupported ? t('export.webmDesc') : t('export.webmNotSupported') }} + {{ + videoSupported + ? t(isDesktop ? 'export.webmDesktopDesc' : 'export.webmBrowserDesc') + : t('export.webmNotSupported') + }}
diff --git a/src/components/HelpDialog.vue b/src/components/HelpDialog.vue index 204b8cf..ca7f550 100644 --- a/src/components/HelpDialog.vue +++ b/src/components/HelpDialog.vue @@ -17,6 +17,7 @@ import { } from '@phosphor-icons/vue' import { Modal } from '@/components/ui' import { t } from '@/i18n' +import { hasDesktopRender } from '@/lib/desktopRenderExport' const props = defineProps<{ modelValue: boolean }>() const emit = defineEmits<{ 'update:modelValue': [value: boolean] }>() @@ -63,6 +64,9 @@ interface Chapter { titleKey: string } +const isDesktop = !!window.ruwioDesktop +const hasDesktopMp4 = hasDesktopRender() + const CHAPTERS: Chapter[] = [ { id: 'getting-started', @@ -509,8 +513,16 @@ const CHAPTERS: Chapter[] = [ { bodyKey: 'help.content.export.formats.runtime' }, { bodyKey: 'help.content.export.formats.scene' }, { bodyKey: 'help.content.export.formats.html' }, - { bodyKey: 'help.content.export.formats.mp4' }, - { bodyKey: 'help.content.export.formats.webm' }, + { + bodyKey: hasDesktopMp4 + ? 'help.content.export.formats.mp4Desktop' + : 'help.content.export.formats.mp4', + }, + { + bodyKey: isDesktop + ? 'help.content.export.formats.webmDesktop' + : 'help.content.export.formats.webm', + }, ], }, { diff --git a/src/i18n/messages.ts b/src/i18n/messages.ts index 96e3a8d..0b062b6 100644 --- a/src/i18n/messages.ts +++ b/src/i18n/messages.ts @@ -39,8 +39,10 @@ export const en = { untitledProject: 'Untitled project', saveProjectDirtyHelp: 'Your project has unsaved changes. Ctrl/Cmd+S writes them to browser storage.', - exportHelp: - 'Save as runtime script, HTML, or video. MP4 needs the render server; WebM records in real time in the browser.', + exportHelpServer: + 'Save as runtime script, HTML, or video. MP4 uses the render server; WebM records in real time with MediaRecorder.', + exportHelpDesktop: + "Save as runtime script, HTML, or video. MP4 renders in the desktop app with bundled ffmpeg; WebM records in Electron's Chromium runtime.", replaceDialog: { title: 'Replace project?', message: @@ -509,10 +511,14 @@ export const en = { sceneDesc: 'Scene data only — requires the runtime to be loaded', exampleTitle: 'Example HTML', exampleDesc: 'Standalone HTML — just open it in a browser', - mp4Badge: 'Server · Frame-accurate', - mp4Desc: 'H.264, any resolution — requires render server', - webmBadge: 'Browser · Realtime', - webmDesc: 'No server — recorded in real time', + mp4ServerBadge: 'Server · Frame-by-frame', + mp4ServerDesc: 'H.264 export via render server', + mp4DesktopBadge: 'Desktop · Frame-by-frame', + mp4DesktopDesc: 'H.264 export via bundled ffmpeg', + webmBrowserBadge: 'Browser · Realtime', + webmBrowserDesc: 'Recorded in real time with MediaRecorder', + webmDesktopBadge: 'Chromium · Realtime', + webmDesktopDesc: "Recorded in real time by Electron's Chromium runtime", webmNotSupported: 'Browser does not support MediaRecorder', gifBadge: 'Browser · Frame-by-frame', gifDesc: '256-colour palette, broadest compatibility', @@ -524,8 +530,10 @@ export const en = { cancel: 'Cancel', failed: 'Export failed', back: 'Back', - labelWebm: 'Rendering WebM (browser, realtime)…', - labelMp4: 'Rendering MP4 (server)…', + labelWebmBrowser: 'Rendering WebM in browser realtime...', + labelWebmDesktop: 'Rendering WebM in Chromium realtime...', + labelMp4Server: 'Rendering MP4 with render server...', + labelMp4Desktop: 'Rendering MP4 in desktop app...', labelGif: 'Rendering GIF (browser, frame-by-frame)…', labelApng: 'Rendering APNG (browser, frame-by-frame)…', labelApngPreview: 'Rendering APNG + preview page…', @@ -1078,9 +1086,13 @@ play html: 'HTML example: A quick standalone page with everything wired up.', mp4: - 'MP4 video: Frame-accurate server render. This needs the render server configured in Settings.', + 'MP4 video: Frame-by-frame H.264 export via the render server.', + mp4Desktop: + 'MP4 video: Frame-by-frame H.264 export in the desktop app with bundled ffmpeg.', webm: - 'WebM video: Browser-side realtime recording. This depends on MediaRecorder support.', + 'WebM video: Browser realtime recording with MediaRecorder.', + webmDesktop: + "WebM video: Realtime recording with MediaRecorder in Electron's Chromium runtime.", }, skipHiddenTitle: 'Skip hidden layers', skipHiddenBody: @@ -1149,8 +1161,10 @@ export const de: DeepPartial = { untitledProject: 'Unbenanntes Projekt', saveProjectDirtyHelp: 'Dein Projekt hat ungespeicherte Änderungen. Mit Ctrl/Cmd+S wird es im Browser gespeichert.', - exportHelp: - 'Als Runtime, HTML oder Video exportieren. MP4 braucht den Render-Server. WebM wird direkt im Browser in Echtzeit aufgenommen.', + exportHelpServer: + 'Als Runtime, HTML oder Video exportieren. MP4 nutzt den Render-Server. WebM wird in Echtzeit mit MediaRecorder aufgenommen.', + exportHelpDesktop: + 'Als Runtime, HTML oder Video exportieren. MP4 rendert in der Desktop-App mit gebündeltem ffmpeg. WebM wird in Electrons Chromium-Runtime aufgenommen.', replaceDialog: { title: 'Projekt ersetzen?', message: @@ -1363,10 +1377,14 @@ export const de: DeepPartial = { sceneDesc: 'Nur Projektdaten: Die Runtime muss schon geladen sein.', exampleTitle: 'HTML-Beispiel', exampleDesc: 'Eigenständige HTML-Datei: Einfach im Browser öffnen.', - mp4Badge: 'Server · Frame-genau', - mp4Desc: 'H.264 in jeder Auflösung: braucht den Render-Server.', - webmBadge: 'Browser · Echtzeit', - webmDesc: 'Ohne Server: direkt im Browser aufgenommen.', + mp4ServerBadge: 'Server · Frame-für-Frame', + mp4ServerDesc: 'H.264-Export über den Render-Server', + mp4DesktopBadge: 'Desktop · Frame-für-Frame', + mp4DesktopDesc: 'H.264-Export über gebündeltes ffmpeg', + webmBrowserBadge: 'Browser · Echtzeit', + webmBrowserDesc: 'Echtzeit-Aufnahme mit MediaRecorder', + webmDesktopBadge: 'Chromium · Echtzeit', + webmDesktopDesc: 'Echtzeit-Aufnahme durch Electrons Chromium-Runtime', webmNotSupported: 'Dieser Browser unterstützt MediaRecorder nicht.', gifBadge: 'Browser · Frame-für-Frame', gifDesc: '256-Farben-Palette, maximale Kompatibilität.', @@ -1378,8 +1396,10 @@ export const de: DeepPartial = { cancel: 'Abbrechen', failed: 'Export fehlgeschlagen', back: 'Zurück', - labelWebm: 'WebM wird gerendert (Browser, Echtzeit)…', - labelMp4: 'MP4 wird gerendert (Server)…', + labelWebmBrowser: 'WebM wird in Browser-Echtzeit gerendert...', + labelWebmDesktop: 'WebM wird in Chromium-Echtzeit gerendert...', + labelMp4Server: 'MP4 wird mit dem Render-Server gerendert...', + labelMp4Desktop: 'MP4 wird in der Desktop-App gerendert...', labelGif: 'GIF wird gerendert (Browser, frame-für-frame)…', labelApng: 'APNG wird gerendert (Browser, frame-für-frame)…', labelApngPreview: 'APNG + Vorschau werden gerendert…', @@ -1920,9 +1940,13 @@ play html: 'HTML-Beispiel: Eine schnelle eigenständige Seite mit allem fertig verdrahtet.', mp4: - 'MP4-Video: Frame-genauer Server-Render. Dafür muss der Render-Server in den Einstellungen konfiguriert sein.', + 'MP4-Video: Frame-für-Frame-H.264-Export über den Render-Server.', + mp4Desktop: + 'MP4-Video: Frame-für-Frame-H.264-Export in der Desktop-App mit gebündeltem ffmpeg.', webm: - 'WebM-Video: Browser-seitige Echtzeit-Aufnahme. Das hängt von MediaRecorder ab.', + 'WebM-Video: Echtzeit-Aufnahme im Browser mit MediaRecorder.', + webmDesktop: + 'WebM-Video: Echtzeit-Aufnahme mit MediaRecorder in Electrons Chromium-Runtime.', }, skipHiddenTitle: 'Versteckte Ebenen auslassen', skipHiddenBody: