Upload video bg via converter extension
| @@ -55,4 +55,15 @@ declare global { | ||
| 55 | 55 | * @param provider Translation provider |
| 56 | 56 | */ |
| 57 | 57 | async function translate(text: string, lang: string, provider: string = null): Promise<string>; |
| 58 | + | |
| 59 | + interface ConvertVideoArgs { | |
| 60 | + buffer: Uint8Array; | |
| 61 | + name: string; | |
| 62 | + } | |
| 63 | + | |
| 64 | + /** | |
| 65 | + * Converts a video file to an animated WebP format using FFmpeg. | |
| 66 | + * @param args - The arguments for the conversion function. | |
| 67 | + */ | |
| 68 | + function convertVideoToAnimatedWebp(args: ConvertVideoArgs): Promise<Uint8Array>; | |
| 58 | 69 | } |
| @@ -4920,7 +4920,7 @@ | ||
| 4920 | 4920 | <div id="bg_menu_content" class="bg_list"> |
| 4921 | 4921 | <form id="form_bg_download" class="bg_example no-border no-shadow" action="javascript:void(null);" method="post" enctype="multipart/form-data"> |
| 4922 | 4922 | <label class="input-file"> |
| 4923 | 4923 | <input type="file" id="add_bg_button" name="avatar" accept="image/png, image/jpeg, image/jpg, image/gif*, imagevideo/bmp*"> |
| 4924 | 4924 | <div class="bg_example no-border no-shadow add_bg_but" style="background-image: url('/img/addbg3.png');"></div> |
| 4925 | 4925 | </label> |
| 4926 | 4926 | </form> |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { Fuse } from '../lib.js'; |
| 2 | 2 | |
| 3 | 3 | import { callPopup, chat_metadata, eventSource, event_types, generateQuietPrompt, getCurrentChatId, getRequestHeaders, getThumbnailUrl, saveSettingsDebounced } from '../script.js'; |
| 4 | 4 | import { openThirdPartyExtensionMenu, saveMetadataDebounced } from './extensions.js'; |
| 5 | 5 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| 6 | 6 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 7 | 7 | import { flashHighlight, stringFormat } from './utils.js'; |
| @@ -77,7 +77,7 @@ function getChatBackgroundsList() { | ||
| 77 | 77 | } |
| 78 | 78 | |
| 79 | 79 | function getBackgroundPath(fileUrl) { |
| 80 | 80 | return `backgrounds/${encodeURIComponent(fileUrl)}`; |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | function highlightLockedBackground() { |
| @@ -438,7 +438,7 @@ async function delBackground(bg) { | ||
| 438 | 438 | }); |
| 439 | 439 | } |
| 440 | 440 | |
| 441 | 441 | async function onBackgroundUploadSelected() { |
| 442 | 442 | const form = $('#form_bg_download').get(0); |
| 443 | 443 | |
| 444 | 444 | if (!(form instanceof HTMLFormElement)) { |
| @@ -447,11 +447,50 @@ function onBackgroundUploadSelected() { | ||
| 447 | 447 | } |
| 448 | 448 | |
| 449 | 449 | const formData = new FormData(form); |
| 450 | + await convertFileIfVideo(formData); | |
| 450 | 451 | uploadBackground(formData); |
| 451 | 452 | form.reset(); |
| 452 | 453 | } |
| 453 | 454 | |
| 454 | 455 | /** |
| 456 | + * Converts a video file to an animated webp format if the file is a video. | |
| 457 | + * @param {FormData} formData | |
| 458 | + * @returns {Promise<void>} | |
| 459 | + */ | |
| 460 | +async function convertFileIfVideo(formData) { | |
| 461 | + const file = formData.get('avatar'); | |
| 462 | + if (!(file instanceof File)) { | |
| 463 | + return; | |
| 464 | + } | |
| 465 | + if (!file.type.startsWith('video/')) { | |
| 466 | + return; | |
| 467 | + } | |
| 468 | + if (typeof globalThis.convertVideoToAnimatedWebp !== 'function') { | |
| 469 | + toastr.warning('Click here to install the Video Background Loader extension', 'Video background uploads require a downloadable add-on', { | |
| 470 | + timeOut: 0, | |
| 471 | + extendedTimeOut: 0, | |
| 472 | + onclick: () => openThirdPartyExtensionMenu('https://github.com/SillyTavern/Extension-VideoBackgroundLoader'), | |
| 473 | + }); | |
| 474 | + return; | |
| 475 | + } | |
| 476 | + | |
| 477 | + let toastMessage = jQuery(); | |
| 478 | + try { | |
| 479 | + toastMessage = toastr.info('Preparing video for upload...', 'Please wait', { timeOut: 0, extendedTimeOut: 0 }); | |
| 480 | + const sourceBuffer = await file.arrayBuffer(); | |
| 481 | + const convertedBuffer = await globalThis.convertVideoToAnimatedWebp({ buffer: new Uint8Array(sourceBuffer), name: file.name }); | |
| 482 | + const convertedFileName = file.name.replace(/\.[^/.]+$/, '.webp'); | |
| 483 | + const convertedFile = new File([convertedBuffer], convertedFileName, { type: 'image/webp' }); | |
| 484 | + formData.set('avatar', convertedFile); | |
| 485 | + toastMessage.remove(); | |
| 486 | + } catch (error) { | |
| 487 | + toastMessage.remove(); | |
| 488 | + console.error('Error converting video to animated webp:', error); | |
| 489 | + toastr.error('Error converting video to animated webp'); | |
| 490 | + } | |
| 491 | +} | |
| 492 | + | |
| 493 | +/** | |
| 455 | 494 | * Uploads a background to the server |
| 456 | 495 | * @param {FormData} formData |
| 457 | 496 | */ |