新增编码方式选择

This commit is contained in:
CN-JS-HuiBai
2026-04-02 17:33:32 +08:00
parent 364438b66d
commit aad2b3db89
4 changed files with 106 additions and 46 deletions

View File

@@ -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();