Merge branch 'AUTOMATIC1111:master' into adjust-ddim-uniform-steps
This commit is contained in:
commit
b88505925b
13 changed files with 1666 additions and 1102 deletions
35
javascript/extensions.js
Normal file
35
javascript/extensions.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
function extensions_apply(_, _){
|
||||||
|
disable = []
|
||||||
|
update = []
|
||||||
|
gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach(function(x){
|
||||||
|
if(x.name.startsWith("enable_") && ! x.checked)
|
||||||
|
disable.push(x.name.substr(7))
|
||||||
|
|
||||||
|
if(x.name.startsWith("update_") && x.checked)
|
||||||
|
update.push(x.name.substr(7))
|
||||||
|
})
|
||||||
|
|
||||||
|
restart_reload()
|
||||||
|
|
||||||
|
return [JSON.stringify(disable), JSON.stringify(update)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function extensions_check(){
|
||||||
|
gradioApp().querySelectorAll('#extensions .extension_status').forEach(function(x){
|
||||||
|
x.innerHTML = "Loading..."
|
||||||
|
})
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_extension_from_index(button, url){
|
||||||
|
button.disabled = "disabled"
|
||||||
|
button.value = "Installing..."
|
||||||
|
|
||||||
|
textarea = gradioApp().querySelector('#extension_to_install textarea')
|
||||||
|
textarea.value = url
|
||||||
|
textarea.dispatchEvent(new Event("input", { bubbles: true }))
|
||||||
|
|
||||||
|
gradioApp().querySelector('#install_extension_button').click()
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,7 @@
|
||||||
" images in this directory. Loaded ": "개의 이미지가 이 경로에 존재합니다. ",
|
" images in this directory. Loaded ": "개의 이미지가 이 경로에 존재합니다. ",
|
||||||
" pages": "페이지로 나뉘어 표시합니다.",
|
" pages": "페이지로 나뉘어 표시합니다.",
|
||||||
", divided into ": "입니다. ",
|
", divided into ": "입니다. ",
|
||||||
|
". Use Installed tab to restart.": "에 성공적으로 설치하였습니다. 설치된 확장기능 탭에서 UI를 재시작해주세요.",
|
||||||
"1st and last digit must be 1. ex:'1, 2, 1'": "1st and last digit must be 1. ex:'1, 2, 1'",
|
"1st and last digit must be 1. ex:'1, 2, 1'": "1st and last digit must be 1. ex:'1, 2, 1'",
|
||||||
"[wiki]": " [위키] 참조",
|
"[wiki]": " [위키] 참조",
|
||||||
"A directory on the same machine where the server is running.": "WebUI 서버가 돌아가고 있는 디바이스에 존재하는 디렉토리를 선택해 주세요.",
|
"A directory on the same machine where the server is running.": "WebUI 서버가 돌아가고 있는 디바이스에 존재하는 디렉토리를 선택해 주세요.",
|
||||||
|
@ -33,22 +34,28 @@
|
||||||
"Always save all generated images": "생성된 이미지 항상 저장하기",
|
"Always save all generated images": "생성된 이미지 항상 저장하기",
|
||||||
"api": "",
|
"api": "",
|
||||||
"append": "뒤에 삽입",
|
"append": "뒤에 삽입",
|
||||||
|
"Append commas": "쉼표 삽입",
|
||||||
|
"Apply and restart UI": "적용 후 UI 재시작",
|
||||||
"Apply color correction to img2img results to match original colors.": "이미지→이미지 결과물이 기존 색상과 일치하도록 색상 보정 적용하기",
|
"Apply color correction to img2img results to match original colors.": "이미지→이미지 결과물이 기존 색상과 일치하도록 색상 보정 적용하기",
|
||||||
"Apply selected styles to current prompt": "현재 프롬프트에 선택된 스타일 적용",
|
"Apply selected styles to current prompt": "현재 프롬프트에 선택된 스타일 적용",
|
||||||
"Apply settings": "설정 적용하기",
|
"Apply settings": "설정 적용하기",
|
||||||
"Auto focal point crop": "초점 기준 크롭(자동 감지)",
|
"Auto focal point crop": "초점 기준 크롭(자동 감지)",
|
||||||
|
"Autocomplete options": "자동완성 설정",
|
||||||
"Batch count": "배치 수",
|
"Batch count": "배치 수",
|
||||||
"Batch from Directory": "저장 경로로부터 여러장 처리",
|
"Batch from Directory": "저장 경로로부터 여러장 처리",
|
||||||
"Batch img2img": "이미지→이미지 배치",
|
"Batch img2img": "이미지→이미지 배치",
|
||||||
"Batch Process": "이미지 여러장 처리",
|
"Batch Process": "이미지 여러장 처리",
|
||||||
"Batch size": "배치 크기",
|
"Batch size": "배치 크기",
|
||||||
|
"behind": "최신 아님",
|
||||||
"BSRGAN 4x": "BSRGAN 4x",
|
"BSRGAN 4x": "BSRGAN 4x",
|
||||||
"built with gradio": "gradio로 제작되었습니다",
|
"built with gradio": "gradio로 제작되었습니다",
|
||||||
"Cancel generate forever": "반복 생성 취소",
|
"Cancel generate forever": "반복 생성 취소",
|
||||||
|
"cfg cnt": "CFG 변화 횟수",
|
||||||
"cfg count": "CFG 변화 횟수",
|
"cfg count": "CFG 변화 횟수",
|
||||||
"CFG Scale": "CFG 스케일",
|
"CFG Scale": "CFG 스케일",
|
||||||
"cfg1 min/max": "CFG1 최소/최대",
|
"cfg1 min/max": "CFG1 최소/최대",
|
||||||
"cfg2 min/max": "CFG2 최소/최대",
|
"cfg2 min/max": "CFG2 최소/최대",
|
||||||
|
"Check for updates": "업데이트 확인",
|
||||||
"Check progress": "진행도 체크",
|
"Check progress": "진행도 체크",
|
||||||
"Check progress (first)": "진행도 체크 (처음)",
|
"Check progress (first)": "진행도 체크 (처음)",
|
||||||
"checkpoint": " 체크포인트 ",
|
"checkpoint": " 체크포인트 ",
|
||||||
|
@ -64,6 +71,9 @@
|
||||||
"CodeFormer weight parameter; 0 = maximum effect; 1 = minimum effect": "CodeFormer 가중치 설정값 (0 = 최대 효과, 1 = 최소 효과)",
|
"CodeFormer weight parameter; 0 = maximum effect; 1 = minimum effect": "CodeFormer 가중치 설정값 (0 = 최대 효과, 1 = 최소 효과)",
|
||||||
"Collect": "즐겨찾기",
|
"Collect": "즐겨찾기",
|
||||||
"Color variation": "색깔 다양성",
|
"Color variation": "색깔 다양성",
|
||||||
|
"Combinations": "조합",
|
||||||
|
"Combinatorial batches": "조합 배치 수",
|
||||||
|
"Combinatorial generation": "조합 생성",
|
||||||
"copy": "복사",
|
"copy": "복사",
|
||||||
"Create a grid where images will have different parameters. Use inputs below to specify which parameters will be shared by columns and rows": "서로 다른 설정값으로 생성된 이미지의 그리드를 만듭니다. 아래의 설정으로 가로/세로에 어떤 설정값을 적용할지 선택하세요.",
|
"Create a grid where images will have different parameters. Use inputs below to specify which parameters will be shared by columns and rows": "서로 다른 설정값으로 생성된 이미지의 그리드를 만듭니다. 아래의 설정으로 가로/세로에 어떤 설정값을 적용할지 선택하세요.",
|
||||||
"Create a text file next to every image with generation parameters.": "생성된 이미지마다 생성 설정값을 담은 텍스트 파일 생성하기",
|
"Create a text file next to every image with generation parameters.": "생성된 이미지마다 생성 설정값을 담은 텍스트 파일 생성하기",
|
||||||
|
@ -78,10 +88,12 @@
|
||||||
"custom fold": "커스텀 경로",
|
"custom fold": "커스텀 경로",
|
||||||
"Custom Name (Optional)": "병합 모델 이름 (선택사항)",
|
"Custom Name (Optional)": "병합 모델 이름 (선택사항)",
|
||||||
"Dataset directory": "데이터셋 경로",
|
"Dataset directory": "데이터셋 경로",
|
||||||
|
"date": "생성 일자",
|
||||||
"DDIM": "DDIM",
|
"DDIM": "DDIM",
|
||||||
"Decode CFG scale": "디코딩 CFG 스케일",
|
"Decode CFG scale": "디코딩 CFG 스케일",
|
||||||
"Decode steps": "디코딩 스텝 수",
|
"Decode steps": "디코딩 스텝 수",
|
||||||
"Delete": "삭제",
|
"Delete": "삭제",
|
||||||
|
"delete next": "선택한 이미지부터 시작해서 삭제할 이미지 갯수",
|
||||||
"Denoising": "디노이징",
|
"Denoising": "디노이징",
|
||||||
"Denoising Diffusion Implicit Models - best at inpainting": "Denoising Diffusion Implicit Models - 인페이팅에 뛰어남",
|
"Denoising Diffusion Implicit Models - best at inpainting": "Denoising Diffusion Implicit Models - 인페이팅에 뛰어남",
|
||||||
"Denoising strength": "디노이즈 강도",
|
"Denoising strength": "디노이즈 강도",
|
||||||
|
@ -108,6 +120,7 @@
|
||||||
"Draw mask": "마스크 직접 그리기",
|
"Draw mask": "마스크 직접 그리기",
|
||||||
"Drop File Here": "파일을 끌어 놓으세요",
|
"Drop File Here": "파일을 끌어 놓으세요",
|
||||||
"Drop Image Here": "이미지를 끌어 놓으세요",
|
"Drop Image Here": "이미지를 끌어 놓으세요",
|
||||||
|
"Dropdown": "드롭다운",
|
||||||
"Embedding": "임베딩",
|
"Embedding": "임베딩",
|
||||||
"Embedding Learning rate": "임베딩 학습률",
|
"Embedding Learning rate": "임베딩 학습률",
|
||||||
"Emphasis: use (text) to make model pay more attention to text and [text] to make it pay less attention": "강조 : (텍스트)를 이용해 모델의 텍스트에 대한 가중치를 더 강하게 주고 [텍스트]를 이용해 더 약하게 줍니다.",
|
"Emphasis: use (text) to make model pay more attention to text and [text] to make it pay less attention": "강조 : (텍스트)를 이용해 모델의 텍스트에 대한 가중치를 더 강하게 주고 [텍스트]를 이용해 더 약하게 줍니다.",
|
||||||
|
@ -127,6 +140,8 @@
|
||||||
"Euler a": "Euler a",
|
"Euler a": "Euler a",
|
||||||
"Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps to higher than 30-40 does not help": "Euler Ancestral - 매우 창의적, 스텝 수에 따라 완전히 다른 결과물이 나올 수 있음. 30~40보다 높은 스텝 수는 효과가 미미함",
|
"Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps to higher than 30-40 does not help": "Euler Ancestral - 매우 창의적, 스텝 수에 따라 완전히 다른 결과물이 나올 수 있음. 30~40보다 높은 스텝 수는 효과가 미미함",
|
||||||
"Existing Caption txt Action": "이미 존재하는 캡션 텍스트 처리",
|
"Existing Caption txt Action": "이미 존재하는 캡션 텍스트 처리",
|
||||||
|
"Extension": "확장기능",
|
||||||
|
"Extensions": "확장기능",
|
||||||
"Extra": "고급",
|
"Extra": "고급",
|
||||||
"Extras": "부가기능",
|
"Extras": "부가기능",
|
||||||
"extras": "부가기능",
|
"extras": "부가기능",
|
||||||
|
@ -134,7 +149,7 @@
|
||||||
"Face restoration": "얼굴 보정",
|
"Face restoration": "얼굴 보정",
|
||||||
"Face restoration model": "얼굴 보정 모델",
|
"Face restoration model": "얼굴 보정 모델",
|
||||||
"Fall-off exponent (lower=higher detail)": "감쇠 지수 (낮을수록 디테일이 올라감)",
|
"Fall-off exponent (lower=higher detail)": "감쇠 지수 (낮을수록 디테일이 올라감)",
|
||||||
"favorites": "즐겨찾기",
|
"Favorites": "즐겨찾기",
|
||||||
"File": "파일",
|
"File": "파일",
|
||||||
"File format for grids": "그리드 이미지 파일 형식",
|
"File format for grids": "그리드 이미지 파일 형식",
|
||||||
"File format for images": "이미지 파일 형식",
|
"File format for images": "이미지 파일 형식",
|
||||||
|
@ -150,6 +165,7 @@
|
||||||
"First Page": "처음 페이지",
|
"First Page": "처음 페이지",
|
||||||
"Firstpass height": "초기 세로길이",
|
"Firstpass height": "초기 세로길이",
|
||||||
"Firstpass width": "초기 가로길이",
|
"Firstpass width": "초기 가로길이",
|
||||||
|
"Fixed seed": "시드 고정",
|
||||||
"Focal point edges weight": "경계면 가중치",
|
"Focal point edges weight": "경계면 가중치",
|
||||||
"Focal point entropy weight": "엔트로피 가중치",
|
"Focal point entropy weight": "엔트로피 가중치",
|
||||||
"Focal point face weight": "얼굴 가중치",
|
"Focal point face weight": "얼굴 가중치",
|
||||||
|
@ -186,6 +202,7 @@
|
||||||
"Image Browser": "이미지 브라우저",
|
"Image Browser": "이미지 브라우저",
|
||||||
"Image for img2img": "Image for img2img",
|
"Image for img2img": "Image for img2img",
|
||||||
"Image for inpainting with mask": "마스크로 인페인팅할 이미지",
|
"Image for inpainting with mask": "마스크로 인페인팅할 이미지",
|
||||||
|
"Image not found (may have been already moved)": "이미지를 찾을 수 없습니다 (이미 옮겨졌을 수 있음)",
|
||||||
"Images Browser": "이미지 브라우저",
|
"Images Browser": "이미지 브라우저",
|
||||||
"Images directory": "이미지 경로",
|
"Images directory": "이미지 경로",
|
||||||
"Images filename pattern": "이미지 파일명 패턴",
|
"Images filename pattern": "이미지 파일명 패턴",
|
||||||
|
@ -205,6 +222,10 @@
|
||||||
"Inpainting conditioning mask strength": "인페인팅 조절 마스크 강도",
|
"Inpainting conditioning mask strength": "인페인팅 조절 마스크 강도",
|
||||||
"Input directory": "인풋 이미지 경로",
|
"Input directory": "인풋 이미지 경로",
|
||||||
"Input images directory": "이미지 경로 입력",
|
"Input images directory": "이미지 경로 입력",
|
||||||
|
"Install": "설치",
|
||||||
|
"Install from URL": "URL로부터 확장기능 설치",
|
||||||
|
"Installed": "설치된 확장기능",
|
||||||
|
"Installed into ": "확장기능을 ",
|
||||||
"Interpolation Method": "보간 방법",
|
"Interpolation Method": "보간 방법",
|
||||||
"Interrogate\nCLIP": "CLIP\n분석",
|
"Interrogate\nCLIP": "CLIP\n분석",
|
||||||
"Interrogate\nDeepBooru": "DeepBooru\n분석",
|
"Interrogate\nDeepBooru": "DeepBooru\n분석",
|
||||||
|
@ -223,6 +244,7 @@
|
||||||
"Just resize": "리사이징",
|
"Just resize": "리사이징",
|
||||||
"Keep -1 for seeds": "시드값 -1로 유지",
|
"Keep -1 for seeds": "시드값 -1로 유지",
|
||||||
"keep whatever was there originally": "이미지 원본 유지",
|
"keep whatever was there originally": "이미지 원본 유지",
|
||||||
|
"keyword": "프롬프트",
|
||||||
"Label": "라벨",
|
"Label": "라벨",
|
||||||
"Lanczos": "Lanczos",
|
"Lanczos": "Lanczos",
|
||||||
"Last prompt:": "마지막 프롬프트 : ",
|
"Last prompt:": "마지막 프롬프트 : ",
|
||||||
|
@ -230,10 +252,12 @@
|
||||||
"Last saved image:": "마지막으로 저장된 이미지 : ",
|
"Last saved image:": "마지막으로 저장된 이미지 : ",
|
||||||
"latent noise": "잠재 노이즈",
|
"latent noise": "잠재 노이즈",
|
||||||
"latent nothing": "잠재 공백",
|
"latent nothing": "잠재 공백",
|
||||||
|
"latest": "최신 버전",
|
||||||
"LDSR": "LDSR",
|
"LDSR": "LDSR",
|
||||||
"LDSR processing steps. Lower = faster": "LDSR 스텝 수. 낮은 값 = 빠른 속도",
|
"LDSR processing steps. Lower = faster": "LDSR 스텝 수. 낮은 값 = 빠른 속도",
|
||||||
"leakyrelu": "leakyrelu",
|
"leakyrelu": "leakyrelu",
|
||||||
"Leave blank to save images to the default path.": "기존 저장 경로에 이미지들을 저장하려면 비워두세요.",
|
"Leave blank to save images to the default path.": "기존 저장 경로에 이미지들을 저장하려면 비워두세요.",
|
||||||
|
"Leave empty for auto": "자동 설정하려면 비워두십시오",
|
||||||
"left": "왼쪽",
|
"left": "왼쪽",
|
||||||
"linear": "linear",
|
"linear": "linear",
|
||||||
"List of prompt inputs": "프롬프트 입력 리스트",
|
"List of prompt inputs": "프롬프트 입력 리스트",
|
||||||
|
@ -242,11 +266,13 @@
|
||||||
"LMS Karras": "LMS Karras",
|
"LMS Karras": "LMS Karras",
|
||||||
"Load": "불러오기",
|
"Load": "불러오기",
|
||||||
"Loading...": "로딩 중...",
|
"Loading...": "로딩 중...",
|
||||||
|
"Local directory name": "로컬 경로 이름",
|
||||||
"Localization (requires restart)": "현지화 (재시작 필요)",
|
"Localization (requires restart)": "현지화 (재시작 필요)",
|
||||||
"Log directory": "로그 경로",
|
"Log directory": "로그 경로",
|
||||||
"Loopback": "루프백",
|
"Loopback": "루프백",
|
||||||
"Loops": "루프 수",
|
"Loops": "루프 수",
|
||||||
"Loss:": "손실(Loss) : ",
|
"Loss:": "손실(Loss) : ",
|
||||||
|
"Magic prompt": "매직 프롬프트",
|
||||||
"Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution": "동일한 시드 값으로 생성되었을 이미지를 주어진 해상도로 최대한 유사하게 재현합니다.",
|
"Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution": "동일한 시드 값으로 생성되었을 이미지를 주어진 해상도로 최대한 유사하게 재현합니다.",
|
||||||
"Make K-diffusion samplers produce same images in a batch as when making a single image": "K-diffusion 샘플러들이 단일 이미지를 생성하는 것처럼 배치에서도 동일한 이미지를 생성하게 하기",
|
"Make K-diffusion samplers produce same images in a batch as when making a single image": "K-diffusion 샘플러들이 단일 이미지를 생성하는 것처럼 배치에서도 동일한 이미지를 생성하게 하기",
|
||||||
"Make Zip when Save?": "저장 시 Zip 생성하기",
|
"Make Zip when Save?": "저장 시 Zip 생성하기",
|
||||||
|
@ -260,7 +286,9 @@
|
||||||
"Minimum number of pages per load": "한번 불러올 때마다 불러올 최소 페이지 수",
|
"Minimum number of pages per load": "한번 불러올 때마다 불러올 최소 페이지 수",
|
||||||
"Modules": "모듈",
|
"Modules": "모듈",
|
||||||
"Move face restoration model from VRAM into RAM after processing": "처리가 완료되면 얼굴 보정 모델을 VRAM에서 RAM으로 옮기기",
|
"Move face restoration model from VRAM into RAM after processing": "처리가 완료되면 얼굴 보정 모델을 VRAM에서 RAM으로 옮기기",
|
||||||
|
"Move to favorites": "즐겨찾기로 옮기기",
|
||||||
"Move VAE and CLIP to RAM when training hypernetwork. Saves VRAM.": "하이퍼네트워크 훈련 진행 시 VAE와 CLIP을 RAM으로 옮기기. VRAM이 절약됩니다.",
|
"Move VAE and CLIP to RAM when training hypernetwork. Saves VRAM.": "하이퍼네트워크 훈련 진행 시 VAE와 CLIP을 RAM으로 옮기기. VRAM이 절약됩니다.",
|
||||||
|
"Moved to favorites": "즐겨찾기로 옮겨짐",
|
||||||
"Multiplier (M) - set to 0 to get model A": "배율 (M) - 0으로 적용하면 모델 A를 얻게 됩니다",
|
"Multiplier (M) - set to 0 to get model A": "배율 (M) - 0으로 적용하면 모델 A를 얻게 됩니다",
|
||||||
"Name": "이름",
|
"Name": "이름",
|
||||||
"Negative prompt": "네거티브 프롬프트",
|
"Negative prompt": "네거티브 프롬프트",
|
||||||
|
@ -285,6 +313,7 @@
|
||||||
"original": "원본 유지",
|
"original": "원본 유지",
|
||||||
"Original negative prompt": "기존 네거티브 프롬프트",
|
"Original negative prompt": "기존 네거티브 프롬프트",
|
||||||
"Original prompt": "기존 프롬프트",
|
"Original prompt": "기존 프롬프트",
|
||||||
|
"Others": "기타",
|
||||||
"Outpainting direction": "아웃페인팅 방향",
|
"Outpainting direction": "아웃페인팅 방향",
|
||||||
"Outpainting mk2": "아웃페인팅 마크 2",
|
"Outpainting mk2": "아웃페인팅 마크 2",
|
||||||
"Output directory": "이미지 저장 경로",
|
"Output directory": "이미지 저장 경로",
|
||||||
|
@ -303,6 +332,7 @@
|
||||||
"Overwrite Old Hypernetwork": "기존 하이퍼네트워크 덮어쓰기",
|
"Overwrite Old Hypernetwork": "기존 하이퍼네트워크 덮어쓰기",
|
||||||
"Page Index": "페이지 인덱스",
|
"Page Index": "페이지 인덱스",
|
||||||
"parameters": "설정값",
|
"parameters": "설정값",
|
||||||
|
"path name": "경로 이름",
|
||||||
"Path to directory where to write outputs": "결과물을 출력할 경로",
|
"Path to directory where to write outputs": "결과물을 출력할 경로",
|
||||||
"Path to directory with input images": "인풋 이미지가 있는 경로",
|
"Path to directory with input images": "인풋 이미지가 있는 경로",
|
||||||
"Paths for saving": "저장 경로",
|
"Paths for saving": "저장 경로",
|
||||||
|
@ -424,6 +454,7 @@
|
||||||
"Skip": "건너뛰기",
|
"Skip": "건너뛰기",
|
||||||
"Slerp angle": "구면 선형 보간 각도",
|
"Slerp angle": "구면 선형 보간 각도",
|
||||||
"Slerp interpolation": "구면 선형 보간",
|
"Slerp interpolation": "구면 선형 보간",
|
||||||
|
"sort by": "정렬 기준",
|
||||||
"Source": "원본",
|
"Source": "원본",
|
||||||
"Source directory": "원본 경로",
|
"Source directory": "원본 경로",
|
||||||
"Split image overlap ratio": "이미지 분할 겹침 비율",
|
"Split image overlap ratio": "이미지 분할 겹침 비율",
|
||||||
|
@ -431,6 +462,7 @@
|
||||||
"Split oversized images": "사이즈가 큰 이미지 분할하기",
|
"Split oversized images": "사이즈가 큰 이미지 분할하기",
|
||||||
"Stable Diffusion": "Stable Diffusion",
|
"Stable Diffusion": "Stable Diffusion",
|
||||||
"Stable Diffusion checkpoint": "Stable Diffusion 체크포인트",
|
"Stable Diffusion checkpoint": "Stable Diffusion 체크포인트",
|
||||||
|
"step cnt": "스텝 변화 횟수",
|
||||||
"step count": "스텝 변화 횟수",
|
"step count": "스텝 변화 횟수",
|
||||||
"step1 min/max": "스텝1 최소/최대",
|
"step1 min/max": "스텝1 최소/최대",
|
||||||
"step2 min/max": "스텝2 최소/최대",
|
"step2 min/max": "스텝2 최소/최대",
|
||||||
|
@ -467,7 +499,9 @@
|
||||||
"txt2img": "텍스트→이미지",
|
"txt2img": "텍스트→이미지",
|
||||||
"txt2img history": "텍스트→이미지 기록",
|
"txt2img history": "텍스트→이미지 기록",
|
||||||
"uniform": "uniform",
|
"uniform": "uniform",
|
||||||
|
"unknown": "알수 없음",
|
||||||
"up": "위쪽",
|
"up": "위쪽",
|
||||||
|
"Update": "업데이트",
|
||||||
"Upload mask": "마스크 업로드하기",
|
"Upload mask": "마스크 업로드하기",
|
||||||
"Upload prompt inputs": "입력할 프롬프트를 업로드하십시오",
|
"Upload prompt inputs": "입력할 프롬프트를 업로드하십시오",
|
||||||
"Upscale Before Restoring Faces": "얼굴 보정을 진행하기 전에 업스케일링 먼저 진행하기",
|
"Upscale Before Restoring Faces": "얼굴 보정을 진행하기 전에 업스케일링 먼저 진행하기",
|
||||||
|
@ -479,9 +513,12 @@
|
||||||
"Upscaler 2 visibility": "업스케일러 2 가시성",
|
"Upscaler 2 visibility": "업스케일러 2 가시성",
|
||||||
"Upscaler for img2img": "이미지→이미지 업스케일러",
|
"Upscaler for img2img": "이미지→이미지 업스케일러",
|
||||||
"Upscaling": "업스케일링",
|
"Upscaling": "업스케일링",
|
||||||
|
"URL for extension's git repository": "확장기능의 git 레포 URL",
|
||||||
"Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition": "저해상도 이미지를 1차적으로 생성 후 업스케일을 진행하여, 이미지의 전체적인 구성을 바꾸지 않고 세부적인 디테일을 향상시킵니다.",
|
"Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition": "저해상도 이미지를 1차적으로 생성 후 업스케일을 진행하여, 이미지의 전체적인 구성을 바꾸지 않고 세부적인 디테일을 향상시킵니다.",
|
||||||
"Use an empty output directory to save pictures normally instead of writing to the output directory.": "저장 경로를 비워두면 기본 저장 폴더에 이미지들이 저장됩니다.",
|
"Use an empty output directory to save pictures normally instead of writing to the output directory.": "저장 경로를 비워두면 기본 저장 폴더에 이미지들이 저장됩니다.",
|
||||||
"Use BLIP for caption": "캡션에 BLIP 사용",
|
"Use BLIP for caption": "캡션에 BLIP 사용",
|
||||||
|
"Use checkbox to enable the extension; it will be enabled or disabled when you click apply button": "체크박스를 이용해 적용할 확장기능을 선택하세요. 변경사항은 적용 후 UI 재시작 버튼을 눌러야 적용됩니다.",
|
||||||
|
"Use checkbox to mark the extension for update; it will be updated when you click apply button": "체크박스를 이용해 업데이트할 확장기능을 선택하세요. 업데이트는 적용 후 UI 재시작 버튼을 눌러야 적용됩니다.",
|
||||||
"Use deepbooru for caption": "캡션에 deepbooru 사용",
|
"Use deepbooru for caption": "캡션에 deepbooru 사용",
|
||||||
"Use dropout": "드롭아웃 사용",
|
"Use dropout": "드롭아웃 사용",
|
||||||
"Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.": "다음 태그들을 사용해 이미지 파일명 형식을 결정하세요 : [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]. 비워두면 기본값으로 설정됩니다.",
|
"Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.": "다음 태그들을 사용해 이미지 파일명 형식을 결정하세요 : [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]. 비워두면 기본값으로 설정됩니다.",
|
||||||
|
|
83
modules/extensions.py
Normal file
83
modules/extensions.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import git
|
||||||
|
|
||||||
|
from modules import paths, shared
|
||||||
|
|
||||||
|
|
||||||
|
extensions = []
|
||||||
|
extensions_dir = os.path.join(paths.script_path, "extensions")
|
||||||
|
|
||||||
|
|
||||||
|
def active():
|
||||||
|
return [x for x in extensions if x.enabled]
|
||||||
|
|
||||||
|
|
||||||
|
class Extension:
|
||||||
|
def __init__(self, name, path, enabled=True):
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self.enabled = enabled
|
||||||
|
self.status = ''
|
||||||
|
self.can_update = False
|
||||||
|
|
||||||
|
repo = None
|
||||||
|
try:
|
||||||
|
if os.path.exists(os.path.join(path, ".git")):
|
||||||
|
repo = git.Repo(path)
|
||||||
|
except Exception:
|
||||||
|
print(f"Error reading github repository info from {path}:", file=sys.stderr)
|
||||||
|
print(traceback.format_exc(), file=sys.stderr)
|
||||||
|
|
||||||
|
if repo is None or repo.bare:
|
||||||
|
self.remote = None
|
||||||
|
else:
|
||||||
|
self.remote = next(repo.remote().urls, None)
|
||||||
|
self.status = 'unknown'
|
||||||
|
|
||||||
|
def list_files(self, subdir, extension):
|
||||||
|
from modules import scripts
|
||||||
|
|
||||||
|
dirpath = os.path.join(self.path, subdir)
|
||||||
|
if not os.path.isdir(dirpath):
|
||||||
|
return []
|
||||||
|
|
||||||
|
res = []
|
||||||
|
for filename in sorted(os.listdir(dirpath)):
|
||||||
|
res.append(scripts.ScriptFile(self.path, filename, os.path.join(dirpath, filename)))
|
||||||
|
|
||||||
|
res = [x for x in res if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def check_updates(self):
|
||||||
|
repo = git.Repo(self.path)
|
||||||
|
for fetch in repo.remote().fetch("--dry-run"):
|
||||||
|
if fetch.flags != fetch.HEAD_UPTODATE:
|
||||||
|
self.can_update = True
|
||||||
|
self.status = "behind"
|
||||||
|
return
|
||||||
|
|
||||||
|
self.can_update = False
|
||||||
|
self.status = "latest"
|
||||||
|
|
||||||
|
def pull(self):
|
||||||
|
repo = git.Repo(self.path)
|
||||||
|
repo.remotes.origin.pull()
|
||||||
|
|
||||||
|
|
||||||
|
def list_extensions():
|
||||||
|
extensions.clear()
|
||||||
|
|
||||||
|
if not os.path.isdir(extensions_dir):
|
||||||
|
return
|
||||||
|
|
||||||
|
for dirname in sorted(os.listdir(extensions_dir)):
|
||||||
|
path = os.path.join(extensions_dir, dirname)
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
continue
|
||||||
|
|
||||||
|
extension = Extension(name=dirname, path=path, enabled=dirname not in shared.opts.disabled_extensions)
|
||||||
|
extensions.append(extension)
|
|
@ -17,6 +17,11 @@ paste_fields = {}
|
||||||
bind_list = []
|
bind_list = []
|
||||||
|
|
||||||
|
|
||||||
|
def reset():
|
||||||
|
paste_fields.clear()
|
||||||
|
bind_list.clear()
|
||||||
|
|
||||||
|
|
||||||
def quote(text):
|
def quote(text):
|
||||||
if ',' not in str(text):
|
if ',' not in str(text):
|
||||||
return text
|
return text
|
||||||
|
|
|
@ -7,7 +7,7 @@ import modules.ui as ui
|
||||||
import gradio as gr
|
import gradio as gr
|
||||||
|
|
||||||
from modules.processing import StableDiffusionProcessing
|
from modules.processing import StableDiffusionProcessing
|
||||||
from modules import shared, paths, script_callbacks
|
from modules import shared, paths, script_callbacks, extensions
|
||||||
|
|
||||||
AlwaysVisible = object()
|
AlwaysVisible = object()
|
||||||
|
|
||||||
|
@ -107,17 +107,8 @@ def list_scripts(scriptdirname, extension):
|
||||||
for filename in sorted(os.listdir(basedir)):
|
for filename in sorted(os.listdir(basedir)):
|
||||||
scripts_list.append(ScriptFile(paths.script_path, filename, os.path.join(basedir, filename)))
|
scripts_list.append(ScriptFile(paths.script_path, filename, os.path.join(basedir, filename)))
|
||||||
|
|
||||||
extdir = os.path.join(paths.script_path, "extensions")
|
for ext in extensions.active():
|
||||||
if os.path.exists(extdir):
|
scripts_list += ext.list_files(scriptdirname, extension)
|
||||||
for dirname in sorted(os.listdir(extdir)):
|
|
||||||
dirpath = os.path.join(extdir, dirname)
|
|
||||||
scriptdirpath = os.path.join(dirpath, scriptdirname)
|
|
||||||
|
|
||||||
if not os.path.isdir(scriptdirpath):
|
|
||||||
continue
|
|
||||||
|
|
||||||
for filename in sorted(os.listdir(scriptdirpath)):
|
|
||||||
scripts_list.append(ScriptFile(dirpath, filename, os.path.join(scriptdirpath, filename)))
|
|
||||||
|
|
||||||
scripts_list = [x for x in scripts_list if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
|
scripts_list = [x for x in scripts_list if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
|
||||||
|
|
||||||
|
@ -127,11 +118,7 @@ def list_scripts(scriptdirname, extension):
|
||||||
def list_files_with_name(filename):
|
def list_files_with_name(filename):
|
||||||
res = []
|
res = []
|
||||||
|
|
||||||
dirs = [paths.script_path]
|
dirs = [paths.script_path] + [ext.path for ext in extensions.active()]
|
||||||
|
|
||||||
extdir = os.path.join(paths.script_path, "extensions")
|
|
||||||
if os.path.exists(extdir):
|
|
||||||
dirs += [os.path.join(extdir, d) for d in sorted(os.listdir(extdir))]
|
|
||||||
|
|
||||||
for dirpath in dirs:
|
for dirpath in dirs:
|
||||||
if not os.path.isdir(dirpath):
|
if not os.path.isdir(dirpath):
|
||||||
|
|
|
@ -40,7 +40,7 @@ parser.add_argument("--lowram", action='store_true', help="load stable diffusion
|
||||||
parser.add_argument("--always-batch-cond-uncond", action='store_true', help="disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram")
|
parser.add_argument("--always-batch-cond-uncond", action='store_true', help="disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram")
|
||||||
parser.add_argument("--unload-gfpgan", action='store_true', help="does not do anything.")
|
parser.add_argument("--unload-gfpgan", action='store_true', help="does not do anything.")
|
||||||
parser.add_argument("--precision", type=str, help="evaluate at this precision", choices=["full", "autocast"], default="autocast")
|
parser.add_argument("--precision", type=str, help="evaluate at this precision", choices=["full", "autocast"], default="autocast")
|
||||||
parser.add_argument("--share", action='store_true', help="use share=True for gradio and make the UI accessible through their site (doesn't work for me but you might have better luck)")
|
parser.add_argument("--share", action='store_true', help="use share=True for gradio and make the UI accessible through their site")
|
||||||
parser.add_argument("--ngrok", type=str, help="ngrok authtoken, alternative to gradio --share", default=None)
|
parser.add_argument("--ngrok", type=str, help="ngrok authtoken, alternative to gradio --share", default=None)
|
||||||
parser.add_argument("--ngrok-region", type=str, help="The region in which ngrok should start.", default="us")
|
parser.add_argument("--ngrok-region", type=str, help="The region in which ngrok should start.", default="us")
|
||||||
parser.add_argument("--codeformer-models-path", type=str, help="Path to directory with codeformer model file(s).", default=os.path.join(models_path, 'Codeformer'))
|
parser.add_argument("--codeformer-models-path", type=str, help="Path to directory with codeformer model file(s).", default=os.path.join(models_path, 'Codeformer'))
|
||||||
|
@ -97,6 +97,8 @@ restricted_opts = {
|
||||||
"outdir_save",
|
"outdir_save",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd_opts.disable_extension_access = cmd_opts.share or cmd_opts.listen
|
||||||
|
|
||||||
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_swinir, devices.device_esrgan, devices.device_scunet, devices.device_codeformer = \
|
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_swinir, devices.device_esrgan, devices.device_scunet, devices.device_codeformer = \
|
||||||
(devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'swinir', 'esrgan', 'scunet', 'codeformer'])
|
(devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'swinir', 'esrgan', 'scunet', 'codeformer'])
|
||||||
|
|
||||||
|
@ -132,6 +134,7 @@ class State:
|
||||||
current_image = None
|
current_image = None
|
||||||
current_image_sampling_step = 0
|
current_image_sampling_step = 0
|
||||||
textinfo = None
|
textinfo = None
|
||||||
|
need_restart = False
|
||||||
|
|
||||||
def skip(self):
|
def skip(self):
|
||||||
self.skipped = True
|
self.skipped = True
|
||||||
|
@ -354,6 +357,12 @@ options_templates.update(options_section(('sampler-params', "Sampler parameters"
|
||||||
'eta_noise_seed_delta': OptionInfo(0, "Eta noise seed delta", gr.Number, {"precision": 0}),
|
'eta_noise_seed_delta': OptionInfo(0, "Eta noise seed delta", gr.Number, {"precision": 0}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
options_templates.update(options_section((None, "Hidden options"), {
|
||||||
|
"disabled_extensions": OptionInfo([], "Disable those extensions"),
|
||||||
|
}))
|
||||||
|
|
||||||
|
options_templates.update()
|
||||||
|
|
||||||
|
|
||||||
class Options:
|
class Options:
|
||||||
data = None
|
data = None
|
||||||
|
@ -365,8 +374,9 @@ class Options:
|
||||||
|
|
||||||
def __setattr__(self, key, value):
|
def __setattr__(self, key, value):
|
||||||
if self.data is not None:
|
if self.data is not None:
|
||||||
if key in self.data:
|
if key in self.data or key in self.data_labels:
|
||||||
self.data[key] = value
|
self.data[key] = value
|
||||||
|
return
|
||||||
|
|
||||||
return super(Options, self).__setattr__(key, value)
|
return super(Options, self).__setattr__(key, value)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import numpy as np
|
||||||
from PIL import Image, PngImagePlugin
|
from PIL import Image, PngImagePlugin
|
||||||
|
|
||||||
|
|
||||||
from modules import sd_hijack, sd_models, localization, script_callbacks
|
from modules import sd_hijack, sd_models, localization, script_callbacks, ui_extensions
|
||||||
from modules.paths import script_path
|
from modules.paths import script_path
|
||||||
|
|
||||||
from modules.shared import opts, cmd_opts, restricted_opts
|
from modules.shared import opts, cmd_opts, restricted_opts
|
||||||
|
@ -671,6 +671,7 @@ def create_ui(wrap_gradio_gpu_call):
|
||||||
import modules.img2img
|
import modules.img2img
|
||||||
import modules.txt2img
|
import modules.txt2img
|
||||||
|
|
||||||
|
parameters_copypaste.reset()
|
||||||
|
|
||||||
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
|
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
|
||||||
txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, _, txt2img_prompt_style_apply, txt2img_save_style, txt2img_paste, token_counter, token_button = create_toprow(is_img2img=False)
|
txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, _, txt2img_prompt_style_apply, txt2img_save_style, txt2img_paste, token_counter, token_button = create_toprow(is_img2img=False)
|
||||||
|
@ -1511,8 +1512,9 @@ def create_ui(wrap_gradio_gpu_call):
|
||||||
column = None
|
column = None
|
||||||
with gr.Row(elem_id="settings").style(equal_height=False):
|
with gr.Row(elem_id="settings").style(equal_height=False):
|
||||||
for i, (k, item) in enumerate(opts.data_labels.items()):
|
for i, (k, item) in enumerate(opts.data_labels.items()):
|
||||||
|
section_must_be_skipped = item.section[0] is None
|
||||||
|
|
||||||
if previous_section != item.section:
|
if previous_section != item.section and not section_must_be_skipped:
|
||||||
if cols_displayed < settings_cols and (items_displayed >= items_per_col or previous_section is None):
|
if cols_displayed < settings_cols and (items_displayed >= items_per_col or previous_section is None):
|
||||||
if column is not None:
|
if column is not None:
|
||||||
column.__exit__()
|
column.__exit__()
|
||||||
|
@ -1531,6 +1533,8 @@ def create_ui(wrap_gradio_gpu_call):
|
||||||
if k in quicksettings_names and not shared.cmd_opts.freeze_settings:
|
if k in quicksettings_names and not shared.cmd_opts.freeze_settings:
|
||||||
quicksettings_list.append((i, k, item))
|
quicksettings_list.append((i, k, item))
|
||||||
components.append(dummy_component)
|
components.append(dummy_component)
|
||||||
|
elif section_must_be_skipped:
|
||||||
|
components.append(dummy_component)
|
||||||
else:
|
else:
|
||||||
component = create_setting_component(k)
|
component = create_setting_component(k)
|
||||||
component_dict[k] = component
|
component_dict[k] = component
|
||||||
|
@ -1572,9 +1576,10 @@ def create_ui(wrap_gradio_gpu_call):
|
||||||
|
|
||||||
def request_restart():
|
def request_restart():
|
||||||
shared.state.interrupt()
|
shared.state.interrupt()
|
||||||
settings_interface.gradio_ref.do_restart = True
|
shared.state.need_restart = True
|
||||||
|
|
||||||
restart_gradio.click(
|
restart_gradio.click(
|
||||||
|
|
||||||
fn=request_restart,
|
fn=request_restart,
|
||||||
inputs=[],
|
inputs=[],
|
||||||
outputs=[],
|
outputs=[],
|
||||||
|
@ -1612,14 +1617,15 @@ def create_ui(wrap_gradio_gpu_call):
|
||||||
interfaces += script_callbacks.ui_tabs_callback()
|
interfaces += script_callbacks.ui_tabs_callback()
|
||||||
interfaces += [(settings_interface, "Settings", "settings")]
|
interfaces += [(settings_interface, "Settings", "settings")]
|
||||||
|
|
||||||
|
extensions_interface = ui_extensions.create_ui()
|
||||||
|
interfaces += [(extensions_interface, "Extensions", "extensions")]
|
||||||
|
|
||||||
with gr.Blocks(css=css, analytics_enabled=False, title="Stable Diffusion") as demo:
|
with gr.Blocks(css=css, analytics_enabled=False, title="Stable Diffusion") as demo:
|
||||||
with gr.Row(elem_id="quicksettings"):
|
with gr.Row(elem_id="quicksettings"):
|
||||||
for i, k, item in quicksettings_list:
|
for i, k, item in quicksettings_list:
|
||||||
component = create_setting_component(k, is_quicksettings=True)
|
component = create_setting_component(k, is_quicksettings=True)
|
||||||
component_dict[k] = component
|
component_dict[k] = component
|
||||||
|
|
||||||
settings_interface.gradio_ref = demo
|
|
||||||
|
|
||||||
parameters_copypaste.integrate_settings_paste_fields(component_dict)
|
parameters_copypaste.integrate_settings_paste_fields(component_dict)
|
||||||
parameters_copypaste.run_bind()
|
parameters_copypaste.run_bind()
|
||||||
|
|
||||||
|
|
268
modules/ui_extensions.py
Normal file
268
modules/ui_extensions.py
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import git
|
||||||
|
|
||||||
|
import gradio as gr
|
||||||
|
import html
|
||||||
|
|
||||||
|
from modules import extensions, shared, paths
|
||||||
|
|
||||||
|
|
||||||
|
available_extensions = {"extensions": []}
|
||||||
|
|
||||||
|
|
||||||
|
def check_access():
|
||||||
|
assert not shared.cmd_opts.disable_extension_access, "extension access disabed because of commandline flags"
|
||||||
|
|
||||||
|
|
||||||
|
def apply_and_restart(disable_list, update_list):
|
||||||
|
check_access()
|
||||||
|
|
||||||
|
disabled = json.loads(disable_list)
|
||||||
|
assert type(disabled) == list, f"wrong disable_list data for apply_and_restart: {disable_list}"
|
||||||
|
|
||||||
|
update = json.loads(update_list)
|
||||||
|
assert type(update) == list, f"wrong update_list data for apply_and_restart: {update_list}"
|
||||||
|
|
||||||
|
update = set(update)
|
||||||
|
|
||||||
|
for ext in extensions.extensions:
|
||||||
|
if ext.name not in update:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
ext.pull()
|
||||||
|
except Exception:
|
||||||
|
print(f"Error pulling updates for {ext.name}:", file=sys.stderr)
|
||||||
|
print(traceback.format_exc(), file=sys.stderr)
|
||||||
|
|
||||||
|
shared.opts.disabled_extensions = disabled
|
||||||
|
shared.opts.save(shared.config_filename)
|
||||||
|
|
||||||
|
shared.state.interrupt()
|
||||||
|
shared.state.need_restart = True
|
||||||
|
|
||||||
|
|
||||||
|
def check_updates():
|
||||||
|
check_access()
|
||||||
|
|
||||||
|
for ext in extensions.extensions:
|
||||||
|
if ext.remote is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
ext.check_updates()
|
||||||
|
except Exception:
|
||||||
|
print(f"Error checking updates for {ext.name}:", file=sys.stderr)
|
||||||
|
print(traceback.format_exc(), file=sys.stderr)
|
||||||
|
|
||||||
|
return extension_table()
|
||||||
|
|
||||||
|
|
||||||
|
def extension_table():
|
||||||
|
code = f"""<!-- {time.time()} -->
|
||||||
|
<table id="extensions">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><abbr title="Use checkbox to enable the extension; it will be enabled or disabled when you click apply button">Extension</abbr></th>
|
||||||
|
<th>URL</th>
|
||||||
|
<th><abbr title="Use checkbox to mark the extension for update; it will be updated when you click apply button">Update</abbr></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
"""
|
||||||
|
|
||||||
|
for ext in extensions.extensions:
|
||||||
|
if ext.can_update:
|
||||||
|
ext_status = f"""<label><input class="gr-check-radio gr-checkbox" name="update_{html.escape(ext.name)}" checked="checked" type="checkbox">{html.escape(ext.status)}</label>"""
|
||||||
|
else:
|
||||||
|
ext_status = ext.status
|
||||||
|
|
||||||
|
code += f"""
|
||||||
|
<tr>
|
||||||
|
<td><label><input class="gr-check-radio gr-checkbox" name="enable_{html.escape(ext.name)}" type="checkbox" {'checked="checked"' if ext.enabled else ''}>{html.escape(ext.name)}</label></td>
|
||||||
|
<td><a href="{html.escape(ext.remote or '')}">{html.escape(ext.remote or '')}</a></td>
|
||||||
|
<td{' class="extension_status"' if ext.remote is not None else ''}>{ext_status}</td>
|
||||||
|
</tr>
|
||||||
|
"""
|
||||||
|
|
||||||
|
code += """
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
"""
|
||||||
|
|
||||||
|
return code
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_git_url(url):
|
||||||
|
if url is None:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
url = url.replace(".git", "")
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
def install_extension_from_url(dirname, url):
|
||||||
|
check_access()
|
||||||
|
|
||||||
|
assert url, 'No URL specified'
|
||||||
|
|
||||||
|
if dirname is None or dirname == "":
|
||||||
|
*parts, last_part = url.split('/')
|
||||||
|
last_part = normalize_git_url(last_part)
|
||||||
|
|
||||||
|
dirname = last_part
|
||||||
|
|
||||||
|
target_dir = os.path.join(extensions.extensions_dir, dirname)
|
||||||
|
assert not os.path.exists(target_dir), f'Extension directory already exists: {target_dir}'
|
||||||
|
|
||||||
|
normalized_url = normalize_git_url(url)
|
||||||
|
assert len([x for x in extensions.extensions if normalize_git_url(x.remote) == normalized_url]) == 0, 'Extension with this URL is already installed'
|
||||||
|
|
||||||
|
tmpdir = os.path.join(paths.script_path, "tmp", dirname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
shutil.rmtree(tmpdir, True)
|
||||||
|
|
||||||
|
repo = git.Repo.clone_from(url, tmpdir)
|
||||||
|
repo.remote().fetch()
|
||||||
|
|
||||||
|
os.rename(tmpdir, target_dir)
|
||||||
|
|
||||||
|
extensions.list_extensions()
|
||||||
|
return [extension_table(), html.escape(f"Installed into {target_dir}. Use Installed tab to restart.")]
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir, True)
|
||||||
|
|
||||||
|
|
||||||
|
def install_extension_from_index(url):
|
||||||
|
ext_table, message = install_extension_from_url(None, url)
|
||||||
|
|
||||||
|
return refresh_available_extensions_from_data(), ext_table, message
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_available_extensions(url):
|
||||||
|
global available_extensions
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
with urllib.request.urlopen(url) as response:
|
||||||
|
text = response.read()
|
||||||
|
|
||||||
|
available_extensions = json.loads(text)
|
||||||
|
|
||||||
|
return url, refresh_available_extensions_from_data(), ''
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_available_extensions_from_data():
|
||||||
|
extlist = available_extensions["extensions"]
|
||||||
|
installed_extension_urls = {normalize_git_url(extension.remote): extension.name for extension in extensions.extensions}
|
||||||
|
|
||||||
|
code = f"""<!-- {time.time()} -->
|
||||||
|
<table id="available_extensions">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Extension</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
"""
|
||||||
|
|
||||||
|
for ext in extlist:
|
||||||
|
name = ext.get("name", "noname")
|
||||||
|
url = ext.get("url", None)
|
||||||
|
description = ext.get("description", "")
|
||||||
|
|
||||||
|
if url is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
existing = installed_extension_urls.get(normalize_git_url(url), None)
|
||||||
|
|
||||||
|
install_code = f"""<input onclick="install_extension_from_index(this, '{html.escape(url)}')" type="button" value="{"Install" if not existing else "Installed"}" {"disabled=disabled" if existing else ""} class="gr-button gr-button-lg gr-button-secondary">"""
|
||||||
|
|
||||||
|
code += f"""
|
||||||
|
<tr>
|
||||||
|
<td><a href="{html.escape(url)}">{html.escape(name)}</a></td>
|
||||||
|
<td>{html.escape(description)}</td>
|
||||||
|
<td>{install_code}</td>
|
||||||
|
</tr>
|
||||||
|
"""
|
||||||
|
|
||||||
|
code += """
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
"""
|
||||||
|
|
||||||
|
return code
|
||||||
|
|
||||||
|
|
||||||
|
def create_ui():
|
||||||
|
import modules.ui
|
||||||
|
|
||||||
|
with gr.Blocks(analytics_enabled=False) as ui:
|
||||||
|
with gr.Tabs(elem_id="tabs_extensions") as tabs:
|
||||||
|
with gr.TabItem("Installed"):
|
||||||
|
|
||||||
|
with gr.Row():
|
||||||
|
apply = gr.Button(value="Apply and restart UI", variant="primary")
|
||||||
|
check = gr.Button(value="Check for updates")
|
||||||
|
extensions_disabled_list = gr.Text(elem_id="extensions_disabled_list", visible=False).style(container=False)
|
||||||
|
extensions_update_list = gr.Text(elem_id="extensions_update_list", visible=False).style(container=False)
|
||||||
|
|
||||||
|
extensions_table = gr.HTML(lambda: extension_table())
|
||||||
|
|
||||||
|
apply.click(
|
||||||
|
fn=apply_and_restart,
|
||||||
|
_js="extensions_apply",
|
||||||
|
inputs=[extensions_disabled_list, extensions_update_list],
|
||||||
|
outputs=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
check.click(
|
||||||
|
fn=check_updates,
|
||||||
|
_js="extensions_check",
|
||||||
|
inputs=[],
|
||||||
|
outputs=[extensions_table],
|
||||||
|
)
|
||||||
|
|
||||||
|
with gr.TabItem("Available"):
|
||||||
|
with gr.Row():
|
||||||
|
refresh_available_extensions_button = gr.Button(value="Load from:", variant="primary")
|
||||||
|
available_extensions_index = gr.Text(value="https://raw.githubusercontent.com/wiki/AUTOMATIC1111/stable-diffusion-webui/Extensions-index.md", label="Extension index URL").style(container=False)
|
||||||
|
extension_to_install = gr.Text(elem_id="extension_to_install", visible=False)
|
||||||
|
install_extension_button = gr.Button(elem_id="install_extension_button", visible=False)
|
||||||
|
|
||||||
|
install_result = gr.HTML()
|
||||||
|
available_extensions_table = gr.HTML()
|
||||||
|
|
||||||
|
refresh_available_extensions_button.click(
|
||||||
|
fn=modules.ui.wrap_gradio_call(refresh_available_extensions, extra_outputs=[gr.update(), gr.update()]),
|
||||||
|
inputs=[available_extensions_index],
|
||||||
|
outputs=[available_extensions_index, available_extensions_table, install_result],
|
||||||
|
)
|
||||||
|
|
||||||
|
install_extension_button.click(
|
||||||
|
fn=modules.ui.wrap_gradio_call(install_extension_from_index, extra_outputs=[gr.update(), gr.update()]),
|
||||||
|
inputs=[extension_to_install],
|
||||||
|
outputs=[available_extensions_table, extensions_table, install_result],
|
||||||
|
)
|
||||||
|
|
||||||
|
with gr.TabItem("Install from URL"):
|
||||||
|
install_url = gr.Text(label="URL for extension's git repository")
|
||||||
|
install_dirname = gr.Text(label="Local directory name", placeholder="Leave empty for auto")
|
||||||
|
install_button = gr.Button(value="Install", variant="primary")
|
||||||
|
install_result = gr.HTML(elem_id="extension_install_result")
|
||||||
|
|
||||||
|
install_button.click(
|
||||||
|
fn=modules.ui.wrap_gradio_call(install_extension_from_url, extra_outputs=[gr.update()]),
|
||||||
|
inputs=[install_dirname, install_url],
|
||||||
|
outputs=[extensions_table, install_result],
|
||||||
|
)
|
||||||
|
|
||||||
|
return ui
|
|
@ -26,3 +26,4 @@ torchdiffeq
|
||||||
kornia
|
kornia
|
||||||
lark
|
lark
|
||||||
inflection
|
inflection
|
||||||
|
GitPython
|
||||||
|
|
|
@ -23,3 +23,4 @@ torchdiffeq==0.2.3
|
||||||
kornia==0.6.7
|
kornia==0.6.7
|
||||||
lark==1.1.2
|
lark==1.1.2
|
||||||
inflection==0.5.1
|
inflection==0.5.1
|
||||||
|
GitPython==3.1.27
|
||||||
|
|
25
style.css
25
style.css
|
@ -530,6 +530,29 @@ img2maskimg, #img2maskimg > .h-60, #img2maskimg > .h-60 > div, #img2maskimg > .h
|
||||||
min-height: 480px !important;
|
min-height: 480px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extensions */
|
||||||
|
|
||||||
|
#tab_extensions table{
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab_extensions table td, #tab_extensions table th{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab_extensions table input[type="checkbox"]{
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab_extensions button{
|
||||||
|
max-width: 16em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab_extensions input[disabled="disabled"]{
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/* The following handles localization for right-to-left (RTL) languages like Arabic.
|
/* The following handles localization for right-to-left (RTL) languages like Arabic.
|
||||||
The rtl media type will only be activated by the logic in javascript/localization.js.
|
The rtl media type will only be activated by the logic in javascript/localization.js.
|
||||||
If you change anything above, you need to make sure it is RTL compliant by just running
|
If you change anything above, you need to make sure it is RTL compliant by just running
|
||||||
|
@ -607,4 +630,4 @@ Then, you will need to add the RTL counterpart only if needed in the rtl section
|
||||||
right: unset;
|
right: unset;
|
||||||
left: 0.5em;
|
left: 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
17
webui.py
17
webui.py
|
@ -9,7 +9,7 @@ from fastapi.middleware.gzip import GZipMiddleware
|
||||||
|
|
||||||
from modules.paths import script_path
|
from modules.paths import script_path
|
||||||
|
|
||||||
from modules import devices, sd_samplers, upscaler
|
from modules import devices, sd_samplers, upscaler, extensions
|
||||||
import modules.codeformer_model as codeformer
|
import modules.codeformer_model as codeformer
|
||||||
import modules.extras
|
import modules.extras
|
||||||
import modules.face_restoration
|
import modules.face_restoration
|
||||||
|
@ -60,6 +60,8 @@ def wrap_gradio_gpu_call(func, extra_outputs=None):
|
||||||
|
|
||||||
|
|
||||||
def initialize():
|
def initialize():
|
||||||
|
extensions.list_extensions()
|
||||||
|
|
||||||
if cmd_opts.ui_debug_mode:
|
if cmd_opts.ui_debug_mode:
|
||||||
shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
|
shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
|
||||||
modules.scripts.load_scripts()
|
modules.scripts.load_scripts()
|
||||||
|
@ -92,15 +94,18 @@ def create_api(app):
|
||||||
api = Api(app, queue_lock)
|
api = Api(app, queue_lock)
|
||||||
return api
|
return api
|
||||||
|
|
||||||
|
|
||||||
def wait_on_server(demo=None):
|
def wait_on_server(demo=None):
|
||||||
while 1:
|
while 1:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
if demo and getattr(demo, 'do_restart', False):
|
if shared.state.need_restart:
|
||||||
|
shared.state.need_restart = False
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
demo.close()
|
demo.close()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
def api_only():
|
def api_only():
|
||||||
initialize()
|
initialize()
|
||||||
|
|
||||||
|
@ -132,14 +137,16 @@ def webui():
|
||||||
|
|
||||||
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||||
|
|
||||||
if (launch_api):
|
if launch_api:
|
||||||
create_api(app)
|
create_api(app)
|
||||||
|
|
||||||
wait_on_server(demo)
|
wait_on_server(demo)
|
||||||
|
|
||||||
sd_samplers.set_samplers()
|
sd_samplers.set_samplers()
|
||||||
|
|
||||||
print('Reloading Custom Scripts')
|
print('Reloading extensions')
|
||||||
|
extensions.list_extensions()
|
||||||
|
print('Reloading custom scripts')
|
||||||
modules.scripts.reload_scripts()
|
modules.scripts.reload_scripts()
|
||||||
print('Reloading modules: modules.ui')
|
print('Reloading modules: modules.ui')
|
||||||
importlib.reload(modules.ui)
|
importlib.reload(modules.ui)
|
||||||
|
@ -148,8 +155,6 @@ def webui():
|
||||||
print('Restarting Gradio')
|
print('Restarting Gradio')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
task = []
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if cmd_opts.nowebui:
|
if cmd_opts.nowebui:
|
||||||
api_only()
|
api_only()
|
||||||
|
|
Loading…
Add table
Reference in a new issue