diff --git a/.env b/.env
new file mode 100644
index 00000000..4153c49f
--- /dev/null
+++ b/.env
@@ -0,0 +1,75 @@
+# AI Service
+NEXT_PUBLIC_SELECT_AI_SERVICE="" # openai, dify, groq, etc.
+NEXT_PUBLIC_SELECT_AI_MODEL="" # gpt-4o, claude-3-5-sonnet-20240620, etc.
+
+# Local LLM
+NEXT_PUBLIC_LOCAL_LLM_URL=""
+NEXT_PUBLIC_LOCAL_LLM_MODEL=""
+
+# Voice
+NEXT_PUBLIC_SELECT_VOICE="" # voicevox, elevenlabs, etc.
+
+# VoiceVox
+NEXT_PUBLIC_VOICEVOX_SPEAKER="" # 46, 47, etc.
+NEXT_PUBLIC_VOICEVOX_SPEED="" # 1.0, 1.2, etc.
+NEXT_PUBLIC_VOICEVOX_PITCH="" # 0.0, 0.2, etc.
+NEXT_PUBLIC_VOICEVOX_INTONATION="" # 1.0, 1.2, etc.
+
+# KoeiroMap
+NEXT_PUBLIC_KOEIROMAP_KEY=""
+
+# Google TTS
+NEXT_PUBLIC_GOOGLE_TTS_TYPE=""
+
+# StyleBertVits2
+NEXT_PUBLIC_STYLEBERTVITS2_MODEL_ID=""
+NEXT_PUBLIC_STYLEBERTVITS2_STYLE=""
+NEXT_PUBLIC_STYLEBERTVITS2_SDP_RATIO=""
+NEXT_PUBLIC_STYLEBERTVITS2_LENGTH=""
+
+STYLEBERTVITS2_SERVER_URL=""
+STYLEBERTVITS2_API_KEY=""
+
+# ElevenLabs
+ELEVENLABS_API_KEY=""
+
+# GSVI TTS
+NEXT_PUBLIC_GSVI_TTS_URL=""
+NEXT_PUBLIC_GSVI_TTS_MODEL_ID=""
+NEXT_PUBLIC_GSVI_TTS_BATCH_SIZE=""
+NEXT_PUBLIC_GSVI_TTS_SPEECH_RATE=""
+
+# Youtube
+NEXT_PUBLIC_YOUTUBE_API_KEY=""
+NEXT_PUBLIC_YOUTUBE_MODE=""
+NEXT_PUBLIC_YOUTUBE_LIVE_ID=""
+
+# Language
+NEXT_PUBLIC_SELECT_LANGUAGE="" # en, ja, etc.
+NEXT_PUBLIC_SELECT_VOICE_LANGUAGE="" # en-US, ja-JP, etc.
+
+# Other
+NEXT_PUBLIC_BACKGROUND_IMAGE_PATH="/bg-c.png"
+NEXT_PUBLIC_SHOW_INTRODUCTION=false
+NEXT_PUBLIC_CHARACTER_NAME=""
+NEXT_PUBLIC_SHOW_ASSISTANT_TEXT=""
+NEXT_PUBLIC_SHOW_CHARACTER_NAME=""
+NEXT_PUBLIC_CHANGE_ENGLISH_TO_JAPANESE=""
+NEXT_PUBLIC_SHOW_CONTROL_PANEL=""
+NEXT_PUBLIC_WEBSOCKET_MODE=""
+NEXT_PUBLIC_SLIDE_MODE=""
+
+# AI API Keys
+OPENAI_KEY=""
+ANTHROPIC_KEY=""
+GOOGLE_KEY=""
+AZURE_KEY=""
+GROQ_KEY=""
+COHERE_KEY=""
+MISTRALAI_KEY=""
+PERPLEXITY_KEY=""
+FIREWORKS_KEY=""
+
+# Dify
+DIFY_KEY=""
+DIFY_URL=""
diff --git a/.env.example b/.env.example
index 7bc01782..4153c49f 100644
--- a/.env.example
+++ b/.env.example
@@ -1,10 +1,75 @@
-GOOGLE_APPLICATION_CREDENTIALS="./credentials.json"
-NEXT_PUBLIC_OPEN_AI_KEY=""
-NEXT_PUBLIC_ANTHROPIC_KEY=""
-NEXT_PUBLIC_GOOGLE_KEY=""
-NEXT_PUBLIC_GROQ_KEY=""
+# AI Service
+NEXT_PUBLIC_SELECT_AI_SERVICE="" # openai, dify, groq, etc.
+NEXT_PUBLIC_SELECT_AI_MODEL="" # gpt-4o, claude-3-5-sonnet-20240620, etc.
+
+# Local LLM
NEXT_PUBLIC_LOCAL_LLM_URL=""
NEXT_PUBLIC_LOCAL_LLM_MODEL=""
-NEXT_PUBLIC_DIFY_KEY=""
-NEXT_PUBLIC_DIFY_URL=""
+
+# Voice
+NEXT_PUBLIC_SELECT_VOICE="" # voicevox, elevenlabs, etc.
+
+# VoiceVox
+NEXT_PUBLIC_VOICEVOX_SPEAKER="" # 46, 47, etc.
+NEXT_PUBLIC_VOICEVOX_SPEED="" # 1.0, 1.2, etc.
+NEXT_PUBLIC_VOICEVOX_PITCH="" # 0.0, 0.2, etc.
+NEXT_PUBLIC_VOICEVOX_INTONATION="" # 1.0, 1.2, etc.
+
+# KoeiroMap
+NEXT_PUBLIC_KOEIROMAP_KEY=""
+
+# Google TTS
NEXT_PUBLIC_GOOGLE_TTS_TYPE=""
+
+# StyleBertVits2
+NEXT_PUBLIC_STYLEBERTVITS2_MODEL_ID=""
+NEXT_PUBLIC_STYLEBERTVITS2_STYLE=""
+NEXT_PUBLIC_STYLEBERTVITS2_SDP_RATIO=""
+NEXT_PUBLIC_STYLEBERTVITS2_LENGTH=""
+
+STYLEBERTVITS2_SERVER_URL=""
+STYLEBERTVITS2_API_KEY=""
+
+# ElevenLabs
+ELEVENLABS_API_KEY=""
+
+# GSVI TTS
+NEXT_PUBLIC_GSVI_TTS_URL=""
+NEXT_PUBLIC_GSVI_TTS_MODEL_ID=""
+NEXT_PUBLIC_GSVI_TTS_BATCH_SIZE=""
+NEXT_PUBLIC_GSVI_TTS_SPEECH_RATE=""
+
+# Youtube
+NEXT_PUBLIC_YOUTUBE_API_KEY=""
+NEXT_PUBLIC_YOUTUBE_MODE=""
+NEXT_PUBLIC_YOUTUBE_LIVE_ID=""
+
+# Language
+NEXT_PUBLIC_SELECT_LANGUAGE="" # en, ja, etc.
+NEXT_PUBLIC_SELECT_VOICE_LANGUAGE="" # en-US, ja-JP, etc.
+
+# Other
+NEXT_PUBLIC_BACKGROUND_IMAGE_PATH="/bg-c.png"
+NEXT_PUBLIC_SHOW_INTRODUCTION=false
+NEXT_PUBLIC_CHARACTER_NAME=""
+NEXT_PUBLIC_SHOW_ASSISTANT_TEXT=""
+NEXT_PUBLIC_SHOW_CHARACTER_NAME=""
+NEXT_PUBLIC_CHANGE_ENGLISH_TO_JAPANESE=""
+NEXT_PUBLIC_SHOW_CONTROL_PANEL=""
+NEXT_PUBLIC_WEBSOCKET_MODE=""
+NEXT_PUBLIC_SLIDE_MODE=""
+
+# AI API Keys
+OPENAI_KEY=""
+ANTHROPIC_KEY=""
+GOOGLE_KEY=""
+AZURE_KEY=""
+GROQ_KEY=""
+COHERE_KEY=""
+MISTRALAI_KEY=""
+PERPLEXITY_KEY=""
+FIREWORKS_KEY=""
+
+# Dify
+DIFY_KEY=""
+DIFY_URL=""
diff --git a/.gitignore b/.gitignore
index 20b435df..247cf22e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,7 +41,6 @@ credentials.json
.tool-versions
certificates
-.env
/public/slides/*
!/public/slides/demo/
diff --git a/docs/README_ko.md b/docs/README_ko.md
index 794e9c57..5dc7f293 100644
--- a/docs/README_ko.md
+++ b/docs/README_ko.md
@@ -45,7 +45,6 @@
- Node.js: ^20.0.0
- npm: 10.8.1
-
## 공통 사전 준비
1. 리포지토리를 로컬에 클론합니다.
diff --git a/docs/README_zh.md b/docs/README_zh.md
index a2500795..33603454 100644
--- a/docs/README_zh.md
+++ b/docs/README_zh.md
@@ -45,7 +45,6 @@
- Node.js: ^20.0.0
- npm: 10.8.1
-
## 共同準備
1. 將存儲庫克隆到本地。
diff --git a/locales/en/translation.json b/locales/en/translation.json
index a237d00c..07bb062e 100644
--- a/locales/en/translation.json
+++ b/locales/en/translation.json
@@ -125,5 +125,14 @@
"PdfConvertLoading": "Converting...",
"PdfConvertSuccess": "Conversion completed",
"PdfConvertError": "Conversion failed",
- "PdfConvertSubmitError": "Please make sure the PDF file, folder name, and API key are set."
+ "PdfConvertSubmitError": "Please make sure the PDF file, folder name, and API key are set.",
+ "LocalStorageReset": "Reset settings (page will be reloaded)",
+ "Errors": {
+ "EmptyAPIKey": "API key is not set",
+ "AIInvalidProperty": "AI service settings are incorrect",
+ "AIAPIError": "An error occurred while executing the AI API",
+ "InvalidAIService": "The selected AI service is not valid",
+ "MethodNotAllowed": "The request is not appropriate",
+ "UnexpectedError": "An unexpected error occurred"
+ }
}
diff --git a/locales/ja/translation.json b/locales/ja/translation.json
index e332a9d3..568cba57 100644
--- a/locales/ja/translation.json
+++ b/locales/ja/translation.json
@@ -126,5 +126,14 @@
"PdfConvertLoading": "変換中...",
"PdfConvertSuccess": "変換が完了しました",
"PdfConvertError": "変換に失敗しました",
- "PdfConvertSubmitError": "PDFファイル、フォルダ名、APIキーが設定されているか確認をしてください"
+ "PdfConvertSubmitError": "PDFファイル、フォルダ名、APIキーが設定されているか確認をしてください",
+ "LocalStorageReset": "設定をリセットする(ページが再読み込みされます)",
+ "Errors": {
+ "EmptyAPIKey": "APIキーが設定されていません",
+ "AIInvalidProperty": "AIサービスの設定値が正しくありません",
+ "AIAPIError": "AI API実行時にエラーが発生しました",
+ "InvalidAIService": "選択しているAIサービスが正しくありません",
+ "MethodNotAllowed": "リクエストが適切でありません",
+ "UnexpectedError": "予期せぬエラーが発生しました"
+ }
}
diff --git a/locales/ko/translation.json b/locales/ko/translation.json
index c7a835c6..9e91783d 100644
--- a/locales/ko/translation.json
+++ b/locales/ko/translation.json
@@ -125,5 +125,14 @@
"PdfConvertLoading": "변환 중...",
"PdfConvertSuccess": "변환 완료",
"PdfConvertError": "변환 실패",
- "PdfConvertSubmitError": "PDF 파일, 폴더 이름, API 키가 설정되어 있는지 확인하세요."
+ "PdfConvertSubmitError": "PDF 파일, 폴더 이름, API 키가 설정되어 있는지 확인하세요.",
+ "LocalStorageReset": "설정을 재설정합니다 (페이지가 다시 로드됩니다)",
+ "Errors": {
+ "EmptyAPIKey": "API 키가 설정되지 않았습니다",
+ "AIInvalidProperty": "AI 서비스 설정값이 올바르지 않습니다",
+ "AIAPIError": "AI API 실행 중 오류가 발생했습니다",
+ "InvalidAIService": "선택한 AI 서비스가 올바르지 않습니다",
+ "MethodNotAllowed": "요청이 적절하지 않습니다",
+ "UnexpectedError": "예기치 않은 오류가 발생했습니다"
+ }
}
diff --git a/locales/zh/translation.json b/locales/zh/translation.json
index d3ef9496..2eba9816 100644
--- a/locales/zh/translation.json
+++ b/locales/zh/translation.json
@@ -125,5 +125,14 @@
"PdfConvertLoading": "转换中...",
"PdfConvertSuccess": "转换完成",
"PdfConvertError": "转换失败",
- "PdfConvertSubmitError": "请确保已设置PDF文件、文件夹名称和API密钥。"
+ "PdfConvertSubmitError": "请确保已设置PDF文件、文件夹名称和API密钥。",
+ "LocalStorageReset": "重設設定(頁面會重新載入)",
+ "Errors": {
+ "EmptyAPIKey": "API 密钥未设置",
+ "AIInvalidProperty": "AI 服务设置值不正确",
+ "AIAPIError": "AI API 执行时发生错误",
+ "InvalidAIService": "选择的 AI 服务不正确",
+ "MethodNotAllowed": "请求不适当",
+ "UnexpectedError": "意外的错误发生"
+ }
}
diff --git a/src/components/introduction.tsx b/src/components/introduction.tsx
index 526096bd..1fde4be4 100644
--- a/src/components/introduction.tsx
+++ b/src/components/introduction.tsx
@@ -12,19 +12,17 @@ import {
} from '@/features/constants/settings'
export const Introduction = () => {
- const dontShowIntroduction = homeStore((s) => s.dontShowIntroduction)
+ const showIntroduction = homeStore((s) => s.showIntroduction)
const selectLanguage = settingsStore((s) => s.selectLanguage)
- const [showIntroduction, setShowIntroduction] = useState(false)
+ const [displayIntroduction, setDisplayIntroduction] = useState(false)
const [opened, setOpened] = useState(true)
const { t } = useTranslation()
useEffect(() => {
- // wait for local storage to be fully initialized
- // to prevent a flash of
- setShowIntroduction(!homeStore.getState().dontShowIntroduction)
- }, [dontShowIntroduction])
+ setDisplayIntroduction(homeStore.getState().showIntroduction)
+ }, [showIntroduction])
const updateLanguage = () => {
console.log('i18n.language', i18n.language)
@@ -54,7 +52,7 @@ export const Introduction = () => {
})
}
- return showIntroduction && opened ? (
+ return displayIntroduction && opened ? (
- {/* dontShowIntroductionのチェックボックスを表示 */}