@file-viewer/renderer-media 2.1.2 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audio.d.ts +2 -2
- package/dist/audio.js +24 -15
- package/dist/index.js +1 -1
- package/dist/video.d.ts +1 -1
- package/dist/video.js +5 -3
- package/package.json +2 -2
package/dist/audio.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type FileRenderContext, type FileViewerRenderedInstance } from '@file-viewer/core';
|
|
2
2
|
/**
|
|
3
3
|
* Pure TypeScript audio renderer.
|
|
4
4
|
*
|
|
5
5
|
* Regular audio files use the browser's native `<audio>` element. MIDI stays in
|
|
6
6
|
* the same async chunk and lazily imports `@tonejs/midi` only for `.mid/.midi`.
|
|
7
7
|
*/
|
|
8
|
-
export default function renderAudio(buffer: ArrayBuffer, target: HTMLDivElement, type?: string): Promise<FileViewerRenderedInstance>;
|
|
8
|
+
export default function renderAudio(buffer: ArrayBuffer, target: HTMLDivElement, type?: string, context?: FileRenderContext): Promise<FileViewerRenderedInstance>;
|
package/dist/audio.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createFileViewerTranslator } from '@file-viewer/core';
|
|
1
2
|
const AUDIO_MIME_MAP = {
|
|
2
3
|
aac: 'audio/aac',
|
|
3
4
|
flac: 'audio/flac',
|
|
@@ -74,7 +75,8 @@ const createRenderedInstance = (target, cleanup) => ({
|
|
|
74
75
|
clearTarget(target);
|
|
75
76
|
}
|
|
76
77
|
});
|
|
77
|
-
const renderAudioElement = (buffer, target, type) => {
|
|
78
|
+
const renderAudioElement = (buffer, target, type, context) => {
|
|
79
|
+
const t = createFileViewerTranslator(context === null || context === void 0 ? void 0 : context.options);
|
|
78
80
|
const normalizedType = type.trim().toLowerCase() || 'mp3';
|
|
79
81
|
const mimeType = AUDIO_MIME_MAP[normalizedType] || 'audio/*';
|
|
80
82
|
const sourceUrl = URL.createObjectURL(new Blob([buffer], { type: mimeType }));
|
|
@@ -83,7 +85,7 @@ const renderAudioElement = (buffer, target, type) => {
|
|
|
83
85
|
const art = createElement('div', 'fv-audio-art');
|
|
84
86
|
art.append(createElement('span'), createElement('i'));
|
|
85
87
|
const copy = createElement('div', 'fv-audio-copy');
|
|
86
|
-
copy.append(createElement('span', 'fv-audio-kicker', normalizedType.toUpperCase() || 'AUDIO'), createElement('strong', '', '
|
|
88
|
+
copy.append(createElement('span', 'fv-audio-kicker', normalizedType.toUpperCase() || 'AUDIO'), createElement('strong', '', t('media.audio.title')), createElement('p', '', t('media.audio.description')));
|
|
87
89
|
const currentTimeText = createElement('span', '', '00:00');
|
|
88
90
|
const durationText = createElement('span', '', '--:--');
|
|
89
91
|
const progressFill = createElement('i');
|
|
@@ -96,7 +98,7 @@ const renderAudioElement = (buffer, target, type) => {
|
|
|
96
98
|
audio.src = sourceUrl;
|
|
97
99
|
audio.controls = true;
|
|
98
100
|
audio.preload = 'metadata';
|
|
99
|
-
audio.textContent = '
|
|
101
|
+
audio.textContent = t('media.audio.unsupported');
|
|
100
102
|
const handleLoadedMetadata = () => {
|
|
101
103
|
durationText.textContent = Number.isFinite(audio.duration) && audio.duration > 0
|
|
102
104
|
? formatDuration(audio.duration)
|
|
@@ -121,14 +123,15 @@ const renderAudioElement = (buffer, target, type) => {
|
|
|
121
123
|
URL.revokeObjectURL(sourceUrl);
|
|
122
124
|
});
|
|
123
125
|
};
|
|
124
|
-
const renderMidiElement = (buffer, target) => {
|
|
126
|
+
const renderMidiElement = (buffer, target, context) => {
|
|
127
|
+
const t = createFileViewerTranslator(context === null || context === void 0 ? void 0 : context.options);
|
|
125
128
|
let disposed = false;
|
|
126
129
|
const root = createElement('div', 'fv-midi-viewer');
|
|
127
130
|
const card = createElement('section', 'fv-midi-card');
|
|
128
131
|
const header = document.createElement('header');
|
|
129
|
-
const title = createElement('strong', '', '
|
|
132
|
+
const title = createElement('strong', '', t('media.midi.title'));
|
|
130
133
|
header.append(createElement('span', '', 'MIDI'), title);
|
|
131
|
-
const body = createElement('div', 'fv-midi-state', '
|
|
134
|
+
const body = createElement('div', 'fv-midi-state', t('media.midi.loading'));
|
|
132
135
|
card.append(header, body);
|
|
133
136
|
root.append(card);
|
|
134
137
|
target.replaceChildren(createStyle(), root);
|
|
@@ -141,7 +144,13 @@ const renderMidiElement = (buffer, target) => {
|
|
|
141
144
|
const table = createElement('table', 'fv-midi-table');
|
|
142
145
|
const thead = document.createElement('thead');
|
|
143
146
|
const headerRow = document.createElement('tr');
|
|
144
|
-
for (const label of [
|
|
147
|
+
for (const label of [
|
|
148
|
+
t('media.midi.trackHeader'),
|
|
149
|
+
t('media.midi.instrumentHeader'),
|
|
150
|
+
t('media.midi.channelHeader'),
|
|
151
|
+
t('media.midi.noteCountHeader'),
|
|
152
|
+
t('media.midi.durationHeader')
|
|
153
|
+
]) {
|
|
145
154
|
headerRow.append(createElement('th', '', label));
|
|
146
155
|
}
|
|
147
156
|
thead.append(headerRow);
|
|
@@ -160,10 +169,10 @@ const renderMidiElement = (buffer, target) => {
|
|
|
160
169
|
const totalNotes = input.tracks.reduce((sum, track) => sum + track.notes, 0);
|
|
161
170
|
const stats = createElement('div', 'fv-midi-stats');
|
|
162
171
|
for (const [label, value] of [
|
|
163
|
-
['
|
|
172
|
+
[t('media.midi.durationStat'), formatDuration(input.duration)],
|
|
164
173
|
['PPQ', String(input.ppq)],
|
|
165
|
-
['
|
|
166
|
-
['
|
|
174
|
+
[t('media.midi.trackStat'), String(input.tracks.length)],
|
|
175
|
+
[t('media.midi.noteStat'), String(totalNotes)]
|
|
167
176
|
]) {
|
|
168
177
|
const stat = document.createElement('div');
|
|
169
178
|
stat.append(createElement('span', '', label), createElement('strong', '', value));
|
|
@@ -179,7 +188,7 @@ const renderMidiElement = (buffer, target) => {
|
|
|
179
188
|
return;
|
|
180
189
|
}
|
|
181
190
|
renderSummary({
|
|
182
|
-
name: midi.name || '
|
|
191
|
+
name: midi.name || t('media.midi.title'),
|
|
183
192
|
duration: midi.duration,
|
|
184
193
|
ppq: midi.header.ppq,
|
|
185
194
|
tracks: midi.tracks.map((track, index) => {
|
|
@@ -196,7 +205,7 @@ const renderMidiElement = (buffer, target) => {
|
|
|
196
205
|
}
|
|
197
206
|
catch (error) {
|
|
198
207
|
if (!disposed) {
|
|
199
|
-
renderError(error instanceof Error ? error.message : '
|
|
208
|
+
renderError(error instanceof Error ? error.message : t('media.midi.parseFailed'));
|
|
200
209
|
}
|
|
201
210
|
}
|
|
202
211
|
})();
|
|
@@ -210,10 +219,10 @@ const renderMidiElement = (buffer, target) => {
|
|
|
210
219
|
* Regular audio files use the browser's native `<audio>` element. MIDI stays in
|
|
211
220
|
* the same async chunk and lazily imports `@tonejs/midi` only for `.mid/.midi`.
|
|
212
221
|
*/
|
|
213
|
-
export default async function renderAudio(buffer, target, type) {
|
|
222
|
+
export default async function renderAudio(buffer, target, type, context) {
|
|
214
223
|
const normalizedType = (type || 'mp3').toLowerCase();
|
|
215
224
|
if (normalizedType === 'midi' || normalizedType === 'mid') {
|
|
216
|
-
return renderMidiElement(buffer, target);
|
|
225
|
+
return renderMidiElement(buffer, target, context);
|
|
217
226
|
}
|
|
218
|
-
return renderAudioElement(buffer, target, normalizedType);
|
|
227
|
+
return renderAudioElement(buffer, target, normalizedType, context);
|
|
219
228
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ if (mediaDefinitions.length !== mediaRendererIds.length) {
|
|
|
5
5
|
throw new Error('@file-viewer/renderer-media could not locate the shared audio/video format definitions.');
|
|
6
6
|
}
|
|
7
7
|
export const mediaRendererDefinitions = mediaDefinitions;
|
|
8
|
-
export const renderFileViewerAudio = (buffer, target, type) => import('./audio.js').then(({ default: renderAudio }) => renderAudio(buffer, target, type));
|
|
8
|
+
export const renderFileViewerAudio = (buffer, target, type, context) => import('./audio.js').then(({ default: renderAudio }) => renderAudio(buffer, target, type, context));
|
|
9
9
|
export const renderFileViewerVideo = (buffer, target, type, context) => import('./video.js').then(({ default: renderVideo }) => renderVideo(buffer, target, type, context));
|
|
10
10
|
export const mediaRenderer = {
|
|
11
11
|
id: 'file-viewer-renderer-media',
|
package/dist/video.d.ts
CHANGED
package/dist/video.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createFileViewerTranslator } from '@file-viewer/core';
|
|
1
2
|
const videoStyle = `
|
|
2
3
|
.fv-video-viewer{width:100%;min-height:100%;display:flex;align-items:center;justify-content:center;padding:28px;background:#eef1f4;box-sizing:border-box}
|
|
3
4
|
.fv-video-shell{width:min(100%,960px);border-radius:8px;border:1px solid rgba(15,23,42,.1);background:#fff;box-shadow:0 18px 48px rgba(15,23,42,.14);overflow:hidden}
|
|
@@ -47,6 +48,7 @@ const createLocalUrl = (buffer, type) => {
|
|
|
47
48
|
* first and imports `hls.js` only when the current browser needs it.
|
|
48
49
|
*/
|
|
49
50
|
export default async function renderVideo(buffer, target, type, context) {
|
|
51
|
+
const t = createFileViewerTranslator(context === null || context === void 0 ? void 0 : context.options);
|
|
50
52
|
const normalizedType = (type || 'mp4').toLowerCase();
|
|
51
53
|
let disposed = false;
|
|
52
54
|
let objectUrl = '';
|
|
@@ -54,14 +56,14 @@ export default async function renderVideo(buffer, target, type, context) {
|
|
|
54
56
|
const root = createElement('div', 'fv-video-viewer');
|
|
55
57
|
const shell = createElement('section', 'fv-video-shell');
|
|
56
58
|
const heading = createElement('div', 'fv-video-heading');
|
|
57
|
-
heading.append(createElement('span', '', normalizedType.toUpperCase() || 'VIDEO'), createElement('strong', '', '
|
|
59
|
+
heading.append(createElement('span', '', normalizedType.toUpperCase() || 'VIDEO'), createElement('strong', '', t('media.video.title')));
|
|
58
60
|
const video = createElement('video', 'fv-video-player');
|
|
59
61
|
video.controls = true;
|
|
60
62
|
video.preload = 'metadata';
|
|
61
|
-
video.textContent = '
|
|
63
|
+
video.textContent = t('media.video.unsupported');
|
|
62
64
|
shell.append(heading, video);
|
|
63
65
|
if (normalizedType === 'm3u8') {
|
|
64
|
-
shell.append(createElement('p', 'fv-video-hint', '
|
|
66
|
+
shell.append(createElement('p', 'fv-video-hint', t('media.video.hlsHint')));
|
|
65
67
|
}
|
|
66
68
|
root.append(shell);
|
|
67
69
|
target.replaceChildren(createStyle(), root);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@file-viewer/renderer-media",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Standalone audio and video renderer plugin for Flyfish File Viewer with native media playback, HLS fallback, MIDI parsing, and offline-friendly lazy loading.",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"LICENSE"
|
|
56
56
|
],
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@file-viewer/core": "^2.1.
|
|
58
|
+
"@file-viewer/core": "^2.1.3",
|
|
59
59
|
"@tonejs/midi": "^2.0.28",
|
|
60
60
|
"hls.js": "^1.6.16"
|
|
61
61
|
},
|