Upload video bg via converter extension
| @@ -55,4 +55,15 @@ declare global { | |||
| 55 | * @param provider Translation provider | 55 | * @param provider Translation provider |
| 56 | */ | 56 | */ |
| 57 | async function translate(text: string, lang: string, provider: string = null): Promise<string>; | 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 | <div id="bg_menu_content" class="bg_list"> | 4920 | <div id="bg_menu_content" class="bg_list"> |
| 4921 | <form id="form_bg_download" class="bg_example no-border no-shadow" action="javascript:void(null);" method="post" enctype="multipart/form-data"> | 4921 | <form id="form_bg_download" class="bg_example no-border no-shadow" action="javascript:void(null);" method="post" enctype="multipart/form-data"> |
| 4922 | <label class="input-file"> | 4922 | <label class="input-file"> |
| 4923 | <input type="file" id="add_bg_button" name="avatar" accept="image/png, image/jpeg, image/jpg, image/gif, image/bmp"> | 4923 | <input type="file" id="add_bg_button" name="avatar" accept="image/*, video/*"> |
| 4924 | <div class="bg_example no-border no-shadow add_bg_but" style="background-image: url('/img/addbg3.png');"></div> | 4924 | <div class="bg_example no-border no-shadow add_bg_but" style="background-image: url('/img/addbg3.png');"></div> |
| 4925 | </label> | 4925 | </label> |
| 4926 | </form> | 4926 | </form> |
| @@ -1,7 +1,7 @@ | |||
| 1 | import { Fuse } from '../lib.js'; | 1 | import { Fuse } from '../lib.js'; |
| 2 | 2 | ||
| 3 | import { callPopup, chat_metadata, eventSource, event_types, generateQuietPrompt, getCurrentChatId, getRequestHeaders, getThumbnailUrl, saveSettingsDebounced } from '../script.js'; | 3 | import { callPopup, chat_metadata, eventSource, event_types, generateQuietPrompt, getCurrentChatId, getRequestHeaders, getThumbnailUrl, saveSettingsDebounced } from '../script.js'; |
| 4 | import { saveMetadataDebounced } from './extensions.js'; | 4 | import { openThirdPartyExtensionMenu, saveMetadataDebounced } from './extensions.js'; |
| 5 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | 5 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| 6 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | 6 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 7 | import { flashHighlight, stringFormat } from './utils.js'; | 7 | import { flashHighlight, stringFormat } from './utils.js'; |
| @@ -77,7 +77,7 @@ function getChatBackgroundsList() { | |||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | function getBackgroundPath(fileUrl) { | 79 | function getBackgroundPath(fileUrl) { |
| 80 | return `backgrounds/${fileUrl}`; | 80 | return `backgrounds/${encodeURIComponent(fileUrl)}`; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | function highlightLockedBackground() { | 83 | function highlightLockedBackground() { |
| @@ -438,7 +438,7 @@ async function delBackground(bg) { | |||
| 438 | }); | 438 | }); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | function onBackgroundUploadSelected() { | 441 | async function onBackgroundUploadSelected() { |
| 442 | const form = $('#form_bg_download').get(0); | 442 | const form = $('#form_bg_download').get(0); |
| 443 | 443 | ||
| 444 | if (!(form instanceof HTMLFormElement)) { | 444 | if (!(form instanceof HTMLFormElement)) { |
| @@ -447,11 +447,50 @@ function onBackgroundUploadSelected() { | |||
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | const formData = new FormData(form); | 449 | const formData = new FormData(form); |
| 450 | await convertFileIfVideo(formData); | ||
| 450 | uploadBackground(formData); | 451 | uploadBackground(formData); |
| 451 | form.reset(); | 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 | * Uploads a background to the server | 494 | * Uploads a background to the server |
| 456 | * @param {FormData} formData | 495 | * @param {FormData} formData |
| 457 | */ | 496 | */ |