구글 ai studio TTS 프롬프트 저장용 tempermonkey스크립트 - 짤방 게시판 | 꿀통넷 - 유튜버 크리에이터 커뮤니티
일반

구글 ai studio TTS 프롬프트 저장용 tempermonkey스크립트

너구리 - 3주 전



템퍼몽키 확장프로그램 설치:

https://chromewebstore.google.com/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo




템퍼몽키가 뭔데 씹덕아?


이거 나도 방에서 배운 크롬 확장 프로그램인데

원래는 크롬확장을 따로 바닥부터 개발해야 특정사이트에 커스텀 기능을 추가할수있는데

그걸 그냥 스크립트 입력만으로 가능하게 해주는 확장프로그램임



이걸로 뭐함?


구글 ai studio TTS 에서 프롬프트를 저장하고 불러오는 기능이 없는데 추가할수있음 아래 스크립트 공유함


!!주의점

브라우저 로컬스토리지라는데 저장하기땜에 캐쉬 초기화같은거 하면 날라감 수요있으면 따로 백업 저장할수있게 기능 추가함




설치방법


우선 위에 템퍼몽키 확장프로그램 설치 링크에서 브라우저에 확장프로그램을 설치


eciJYTn5dSz213Ly0ocFLRFXFVu4Ra8HN9Hquz1t.png


툴바에서 위 모양 아이콘 클릭하면 메뉴가 나오는데


gBPsnLQcpxtLju4AyAAOmTdfnnNZAPdJPY7y1lSt.png



새스크립트 만들기 누르고


MuXn557z6D73CBUv5exdVXM3mN164P677UNEDhvD.png


이런화면이 나오는데 이글 제일 밑에 있는 스크립트 전문 복사해서 붙여넣고 [파일] -> [저장]으로 저장해놓으면



아래 구글 TTS에서 사용 가능해짐

https://aistudio.google.com/generate-speech


일단 테스트버전이라

Single-spekeraudio에서 만 사용 가능하고


HE4ELHjD9zLUyZxBGXnrhbQjBdHW6kmzRyr3lFzm.png


위와같은 방식으로 사용 가능하니까 참고바람



스크립트 전문


// ==UserScript==

// @name Google AI Studio 프리셋 관리

// @namespace http://tampermonkey.net/

// @version 1.0

// @description Google AI Studio 음성 생성 페이지에 프리셋 저장/불러오기 기능 추가

// @author You

// @match https://aistudio.google.com/generate-speech*

// @grant none

// ==/UserScript==


(function() {

'use strict';


// 로컬스토리지 키

const PRESETS_KEY = 'aistudio_voice_presets';


// 프리셋 저장/불러오기 함수들

function getPresets() {

const presets = localStorage.getItem(PRESETS_KEY);

return presets ? JSON.parse(presets) : {};

}


function savePreset(name, content) {

const presets = getPresets();

presets[name] = content;

localStorage.setItem(PRESETS_KEY, JSON.stringify(presets));

}


function deletePreset(name) {

const presets = getPresets();

delete presets[name];

localStorage.setItem(PRESETS_KEY, JSON.stringify(presets));

}


// Style instructions 텍스트에리어 찾기

function getStyleTextarea() {

return document.querySelector('textarea[aria-label="Style instructions"]');

}


// 페이지가 완전히 로드될 때까지 대기

function waitForElement(selector, callback) {

const observer = new MutationObserver((mutations, obs) => {

const element = document.querySelector(selector);

if (element) {

obs.disconnect();

callback(element);

}

});


observer.observe(document.body, {

childList: true,

subtree: true

});


// 이미 존재하는 경우 즉시 실행

const existingElement = document.querySelector(selector);

if (existingElement) {

callback(existingElement);

}

}


// 셀렉트박스 생성 함수

function createPresetSelect() {

const container = document.createElement('div');

container.style.cssText = `

margin: 10px 0;

padding: 10px;

border: 1px solid #dadce0;

border-radius: 8px;

background-color: #f8f9fa;

`;


const label = document.createElement('label');

label.textContent = '저장된 프리셋:';

label.style.cssText = `

display: block;

margin-bottom: 5px;

font-size: 14px;

font-weight: 500;

color: #3c4043;

`;


const selectContainer = document.createElement('div');

selectContainer.style.cssText = `

display: flex;

gap: 8px;

align-items: stretch;

width: 100%;

`;


const select = document.createElement('select');

select.style.cssText = `

flex: 1;

min-width: 0;

padding: 8px 12px;

border: 1px solid #dadce0;

border-radius: 4px;

background-color: white;

color: #3c4043;

font-size: 14px;

cursor: pointer;

height: 36px;

`;


const loadButton = document.createElement('button');

loadButton.textContent = '불러오기';

loadButton.style.cssText = `

background-color: #1a73e8;

color: white;

border: none;

padding: 8px 12px;

border-radius: 4px;

cursor: pointer;

font-size: 14px;

height: 36px;

white-space: nowrap;

min-width: 70px;

transition: background-color 0.3s;

`;


const deleteButton = document.createElement('button');

deleteButton.textContent = '삭제';

deleteButton.style.cssText = `

background-color: #ea4335;

color: white;

border: none;

padding: 8px 12px;

border-radius: 4px;

cursor: pointer;

font-size: 14px;

height: 36px;

white-space: nowrap;

min-width: 50px;

transition: background-color 0.3s;

`;


// 프리셋 목록 업데이트

function updatePresetList() {

const presets = getPresets();


// 기존 옵션들 모두 제거

while (select.firstChild) {

select.removeChild(select.firstChild);

}


// 기본 옵션 추가

const defaultOption = document.createElement('option');

defaultOption.value = '';

defaultOption.textContent = '-- 프리셋 선택 --';

select.appendChild(defaultOption);


// 프리셋 옵션들 추가

Object.keys(presets).forEach(name => {

const option = document.createElement('option');

option.value = name;

option.textContent = name;

select.appendChild(option);

});

}


// 불러오기 버튼 이벤트

loadButton.onclick = () => {

const selectedPreset = select.value;

if (!selectedPreset) {

alert('불러올 프리셋을 선택해주세요.');

return;

}


const presets = getPresets();

const content = presets[selectedPreset];

const textarea = getStyleTextarea();


if (textarea && content) {

textarea.value = content;

// Angular의 변경 감지를 위해 이벤트 발생

textarea.dispatchEvent(new Event('input', { bubbles: true }));

textarea.dispatchEvent(new Event('change', { bubbles: true }));

alert(`프리셋 "${selectedPreset}"이 불러와졌습니다.`);

} else {

alert('텍스트에리어를 찾을 수 없거나 프리셋 내용이 없습니다.');

}

};


// 삭제 버튼 이벤트

deleteButton.onclick = () => {

const selectedPreset = select.value;

if (!selectedPreset) {

alert('삭제할 프리셋을 선택해주세요.');

return;

}


if (confirm(`프리셋 "${selectedPreset}"을(를) 삭제하시겠습니까?`)) {

deletePreset(selectedPreset);

updatePresetList();

alert(`프리셋 "${selectedPreset}"이 삭제되었습니다.`);

}

};


// 호버 효과

loadButton.onmouseover = () => loadButton.style.backgroundColor = '#1557b0';

loadButton.onmouseout = () => loadButton.style.backgroundColor = '#1a73e8';

deleteButton.onmouseover = () => deleteButton.style.backgroundColor = '#d33b2c';

deleteButton.onmouseout = () => deleteButton.style.backgroundColor = '#ea4335';


selectContainer.appendChild(select);

selectContainer.appendChild(loadButton);

selectContainer.appendChild(deleteButton);

container.appendChild(label);

container.appendChild(selectContainer);


// 초기 프리셋 목록 로드

updatePresetList();


// 전역에서 접근 가능하도록 함수 저장

container.updatePresetList = updatePresetList;


return container;

}


// 저장 버튼 생성 함수

function createSaveButton() {

const button = document.createElement('button');

button.textContent = '프리셋 저장';

button.style.cssText = `

background-color: #34a853;

color: white;

border: none;

padding: 8px 16px;

border-radius: 4px;

cursor: pointer;

margin: 10px 0;

font-size: 14px;

transition: background-color 0.3s;

`;


// 호버 효과

button.onmouseover = () => button.style.backgroundColor = '#2d8f45';

button.onmouseout = () => button.style.backgroundColor = '#34a853';


// 클릭 이벤트

button.onclick = () => {

const textarea = getStyleTextarea();

if (!textarea) {

alert('Style instructions 텍스트에리어를 찾을 수 없습니다.');

return;

}


const content = textarea.value.trim();

if (!content) {

alert('저장할 내용이 없습니다.');

return;

}


const presetName = prompt('프리셋 이름을 입력해주세요:');

if (!presetName || !presetName.trim()) {

return;

}


const trimmedName = presetName.trim();

const existingPresets = getPresets();


if (existingPresets[trimmedName]) {

if (!confirm(`프리셋 "${trimmedName}"이 이미 존재합니다. 덮어쓰시겠습니까?`)) {

return;

}

}


savePreset(trimmedName, content);

alert(`프리셋 "${trimmedName}"이 저장되었습니다.`);


// 셀렉트박스 업데이트

const selectContainer = document.querySelector('.preset-select-container');

if (selectContainer && selectContainer.updatePresetList) {

selectContainer.updatePresetList();

}

};


return button;

}


// .settings-content에 셀렉트박스 추가

waitForElement('.settings-content', (settingsContent) => {

console.log('settings-content 요소를 찾았습니다!');


// 이미 추가되었는지 확인

if (!settingsContent.querySelector('.preset-select-container')) {

const presetSelect = createPresetSelect();

presetSelect.classList.add('preset-select-container');


// settings-content의 첫 번째 자식으로 추가

settingsContent.insertBefore(presetSelect, settingsContent.firstChild);


console.log('프리셋 셀렉트박스가 추가되었습니다!');

}

});


// .single-speaker-prompt-builder-wrapper에 저장 버튼 추가

waitForElement('.single-speaker-prompt-builder-wrapper.ng-star-inserted', (wrapper) => {

console.log('single-speaker-prompt-builder-wrapper 요소를 찾았습니다!');


// 이미 추가되었는지 확인

if (!wrapper.querySelector('.preset-save-button')) {

const saveButton = createSaveButton();

saveButton.classList.add('preset-save-button');


// wrapper의 첫 번째 자식으로 추가

wrapper.insertBefore(saveButton, wrapper.firstChild);


console.log('저장 버튼이 추가되었습니다!');

}

});


// 페이지 변경 감지 (SPA 대응)

let currentUrl = location.href;

const urlObserver = new MutationObserver(() => {

if (location.href !== currentUrl) {

currentUrl = location.href;

// URL이 변경되면 다시 요소 추가 시도

setTimeout(() => {

waitForElement('.settings-content', (settingsContent) => {

if (!settingsContent.querySelector('.preset-select-container')) {

const presetSelect = createPresetSelect();

presetSelect.classList.add('preset-select-container');

settingsContent.insertBefore(presetSelect, settingsContent.firstChild);

}

});


waitForElement('.single-speaker-prompt-builder-wrapper.ng-star-inserted', (wrapper) => {

if (!wrapper.querySelector('.preset-save-button')) {

const saveButton = createSaveButton();

saveButton.classList.add('preset-save-button');

wrapper.insertBefore(saveButton, wrapper.firstChild);

}

});

}, 1000);

}

});


urlObserver.observe(document.body, {

childList: true,

subtree: true

});


})();

댓글 (0)

꿀통넷 공식 카카오톡 채팅방

꿀통넷 공식 카카오톡 채팅방에 참여하여 편하게 유튜브 이야기를 나눠보세요! 900명 이상 참여중!

채팅방 참여하기