로그인
[일반]

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

· · 조회 601 댓글 0



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

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

아직 댓글이 없습니다.

유튜브 크리에이터 게시판 목록

전체보기
번호 분류 제목 작성자 추천 조회 작성일
391 일반 [요약번역] 저희채널도 수창정지되어버렸습니다 - 일본롱폼 수창정지 너구리 2 1,141 01.16 368 일반 미스터비스트, Ai가 수백만 크리에이터에 악영향끼칠것.gisa 너구리 0 408 01.13 348 일반 [협조바람] 지금 KBS추적60분 담당자분이랑 컨택중임 ㅇㅈㄷㄱ 1 585 01.12 329 일반 [저장용] 잘 안풀릴때 보면 기분 좋아지는 크갤펌 지표 ㅇㅈㄷㄱ 0 409 01.10 317 일반 ㄹㅇ 딸깍으로 17억 버는법 뉴스로 공개됨 ㅇㅈㄷㄱ 0 643 01.09 316 일반 김프로 연간수입 후덜덜덜덜덜 ㅇㅈㄷㄱ 0 441 01.09 294 일반 카톡 숏폼 크리에이터 모집한다고함 ㅇㅈㄷㄱ 0 408 01.07 215 일반 영 가디언지, 조회수630억 수익1700억 AI쓰레기가 유튜브 잠식 너구리 0 358 12.28 198 일반 실시간으로 꿀붕이들 수익 박살나는중 너구리 0 468 12.26 188 일반 [뉴스] 유튜브에서 가짜뉴스 퍼트리면 손해배상 정보통신망법 개정안 통과 너구리 0 370 12.25 181 일반 [뉴스] 유튜버들 어쩌나.. 숏폼에 지친 MZ세대 다시 블로그 갬성으로 ㅂㅌㅂㅌ 1 442 12.24 174 일반 [뉴스] 경찰 바디캠 Ai가짜영상에 경찰 나섰다 너구리 0 419 12.23 169 일반 [뉴스] 유튜브, 가짜 영화예고편에 칼질 시작 너구리 1 333 12.23 168 일반 [공식] 유튜브, 코딩없이 게임제작하고 유튜브에서 플레이하는 "플레이어블스 빌더 베타" 출시 너구리 0 313 12.23 157 일반 [공식] 유튜브가 싫어요 버튼을 숨기려고 테스트중이라고함 너구리 4 818 12.22 137 일반 본방을 따잇해버린 서브방... 너구리 0 293 12.20 131 일반 내이름은 김춘삼 - 제 강의만 들으시면 누구나 월 천만 원 버실 수 있습니다 너구리 0 282 12.20 112 일지 [뉴스] 유튜브, 크리에이터를 AI 챗봇으로 전환하는 'Portraits' 시작 너구리 0 250 12.18 96 일반 해외에서 인기라는 고추장 쿠키... ㅇㅈㄷㄱ 0 265 12.16 85 일반 보람튜브 근황.news 너구리 1 408 12.15 71 일반 유튜브 망하는법 5가지 너구리 1 549 12.13 70 일반 [뉴스] 미국 유튜버 지급수단 스테이블 코인 추가 너구리 1 263 12.13 50 해외타겟 VOICEVOX 롱폼용 음성 + 자막 자동생성 템퍼몽키 스크립트 너구리 2 1,408 10.29 46 일반 구글 ai studio TTS 프롬프트 저장용 tempermonkey스크립트 너구리 1 601 06.25 45 해외타겟 재미나이 TTS 설정값 (30대 데카이옵빠이 미시 목소리) 너구리 2 851 06.17 44 해외타겟 일본에서 최근 떡상중인곡 - 오지상코분(아저씨문체)[번역있음] 너구리 0 451 06.16 43 해외타겟 일본타겟 참고영상 - 일본의 탈모빔 채널 너구리 0 596 06.15 40 일반 [뉴스] 지그재그, 유튜브 쇼핑 제휴…국내 패션 플랫폼 최초 너구리 0 436 06.11 37 해외타겟 일본타겟 참고영상 - 2025년 최고 JPOP명곡 「잔크렉서스」 너구리 0 466 06.10 35 꿀통 비회원 보이나? 엄지형 0 630 06.08 33 해외타겟 일본 타겟 vpn 써라 jotgosu 1 679 06.07 31 해외타겟 일본타겟 참고영상 - "망X 손가락으로 벌려서 보여주는데 천엔" 너구리 0 526 06.07 29 해외타겟 일본타겟 참고영상 - 건방진 MZ부하를 기세로 제합하는 상사 [번역있음] 너구리 0 525 06.06