新增编码方式选择
This commit is contained in:
@@ -2,6 +2,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const videoListEl = document.getElementById('video-list');
|
||||
const loadingSpinner = document.getElementById('loading-spinner');
|
||||
const refreshBtn = document.getElementById('refresh-btn');
|
||||
const codecSelect = document.getElementById('codec-select');
|
||||
const playerOverlay = document.getElementById('player-overlay');
|
||||
const transcodingOverlay = document.getElementById('transcoding-overlay');
|
||||
const videoPlayer = document.getElementById('video-player');
|
||||
@@ -30,46 +31,54 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a tree structure from S3 keys
|
||||
// Build a tree structure from S3 keys, preserving original object storage directories
|
||||
const tree = {};
|
||||
data.videos.forEach(key => {
|
||||
const parts = key.split('/');
|
||||
let current = tree;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const part = parts[i];
|
||||
parts.forEach((part, index) => {
|
||||
if (!current[part]) {
|
||||
current[part] = (i === parts.length - 1) ? key : {};
|
||||
current[part] = {};
|
||||
}
|
||||
if (i < parts.length - 1) {
|
||||
current = current[part];
|
||||
|
||||
if (index === parts.length - 1) {
|
||||
current[part].__file = key;
|
||||
}
|
||||
}
|
||||
|
||||
current = current[part];
|
||||
});
|
||||
});
|
||||
|
||||
const createFileItem = (name, key) => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'video-item file-item';
|
||||
const ext = name.split('.').pop().toUpperCase();
|
||||
li.innerHTML = `
|
||||
<div class="video-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 8-6 4 6 4V8Z"/><rect width="14" height="12" x="2" y="6" rx="2" ry="2"/></svg>
|
||||
</div>
|
||||
<div class="video-info">
|
||||
<div class="video-title" title="${key}">${name}</div>
|
||||
<div class="video-meta">Video / ${ext}</div>
|
||||
</div>
|
||||
`;
|
||||
li.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
selectVideo(key, li);
|
||||
});
|
||||
return li;
|
||||
};
|
||||
|
||||
// Recursive function to render the tree
|
||||
const renderTree = (node, container) => {
|
||||
for (const [name, value] of Object.entries(node)) {
|
||||
if (typeof value === 'string') {
|
||||
// It's a file
|
||||
const li = document.createElement('li');
|
||||
li.className = 'video-item file-item';
|
||||
const ext = name.split('.').pop().toUpperCase();
|
||||
li.innerHTML = `
|
||||
<div class="video-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 8-6 4 6 4V8Z"/><rect width="14" height="12" x="2" y="6" rx="2" ry="2"/></svg>
|
||||
</div>
|
||||
<div class="video-info">
|
||||
<div class="video-title" title="${value}">${name}</div>
|
||||
<div class="video-meta">Video / ${ext}</div>
|
||||
</div>
|
||||
`;
|
||||
li.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
selectVideo(value, li);
|
||||
});
|
||||
container.appendChild(li);
|
||||
} else {
|
||||
// It's a folder
|
||||
if (name === '__file') continue;
|
||||
|
||||
const childKeys = Object.keys(value).filter(key => key !== '__file');
|
||||
const hasChildren = childKeys.length > 0;
|
||||
const isFile = typeof value.__file === 'string';
|
||||
|
||||
if (hasChildren) {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'folder-item';
|
||||
|
||||
@@ -95,9 +104,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
li.appendChild(folderHeader);
|
||||
if (isFile) {
|
||||
subListContainer.appendChild(createFileItem(name, value.__file));
|
||||
}
|
||||
renderTree(value, subListContainer);
|
||||
li.appendChild(subListContainer);
|
||||
container.appendChild(li);
|
||||
} else if (isFile) {
|
||||
container.appendChild(createFileItem(name, value.__file));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -127,10 +141,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
transcodingOverlay.classList.remove('hidden');
|
||||
|
||||
try {
|
||||
const codec = codecSelect?.value || 'h264';
|
||||
const res = await fetch('/api/transcode', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ key })
|
||||
body: JSON.stringify({ key, codec })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user