增加语音对话功能
This commit is contained in:
@@ -752,3 +752,215 @@
|
||||
.chatpapers-cite-btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* --- Voice lecture pane --- */
|
||||
.chatpapers-lecture-root {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-empty {
|
||||
padding: 20px 12px;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-status {
|
||||
padding: 8px 10px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
background: color-mix(in srgb, #1f7a8c 10%, transparent);
|
||||
border: 1px solid color-mix(in srgb, #1f7a8c 22%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-status[data-status="failed"] {
|
||||
background: color-mix(in srgb, #dc2626 10%, transparent);
|
||||
border-color: color-mix(in srgb, #dc2626 25%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-status[data-status="ready"] {
|
||||
background: color-mix(in srgb, #16a34a 10%, transparent);
|
||||
border-color: color-mix(in srgb, #16a34a 25%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 14px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: #1f7a8c;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-primary:hover:not(:disabled) {
|
||||
background: #186678;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-status-text {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-primary:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 14px;
|
||||
border: 1px solid color-mix(in srgb, #1f7a8c 35%, transparent);
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-secondary:hover:not(:disabled) {
|
||||
background: color-mix(in srgb, #1f7a8c 10%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-secondary:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-tts-meta {
|
||||
font-size: 12px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-audio {
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-btn-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-hint {
|
||||
font-size: 11px;
|
||||
opacity: 0.65;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-player {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-player-title {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid color-mix(in srgb, #1f7a8c 18%, transparent);
|
||||
border-radius: 8px;
|
||||
background: color-mix(in srgb, #1f7a8c 4%, transparent);
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-item:hover:not(:disabled) {
|
||||
background: color-mix(in srgb, #1f7a8c 10%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-item.is-active {
|
||||
border-color: color-mix(in srgb, #16a34a 45%, transparent);
|
||||
background: color-mix(in srgb, #16a34a 10%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-item.is-pending {
|
||||
opacity: 0.55;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-type {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
opacity: 0.65;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-title {
|
||||
font-size: 12px;
|
||||
line-height: 1.35;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-beat-status {
|
||||
flex-shrink: 0;
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-player-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-player-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border: 1px solid color-mix(in srgb, #1f7a8c 30%, transparent);
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.chatpapers-lecture-player-btn:hover {
|
||||
background: color-mix(in srgb, #1f7a8c 12%, transparent);
|
||||
}
|
||||
|
||||
.chatpapers-lecture-error {
|
||||
padding: 12px;
|
||||
color: #dc2626;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<!-- ChatPapers voice lecture: paper + headphones -->
|
||||
<path
|
||||
fill="context-fill"
|
||||
fill-opacity="0.92"
|
||||
d="M3.2 2.8h7.4c.4 0 .7.15.95.4l2.05 2.1c.25.25.4.58.4.95V14.2c0 .9-.73 1.63-1.63 1.63H3.2c-.9 0-1.63-.73-1.63-1.63V4.43C1.57 3.53 2.3 2.8 3.2 2.8z"
|
||||
/>
|
||||
<path
|
||||
fill="context-fill"
|
||||
fill-opacity="0.35"
|
||||
d="M10.6 2.85v2.35c0 .45.37.82.82.82h2.35L10.6 2.85z"
|
||||
/>
|
||||
<path
|
||||
stroke="context-stroke"
|
||||
stroke-opacity="0.55"
|
||||
stroke-width="0.9"
|
||||
stroke-linecap="round"
|
||||
d="M4.35 7.1h5.1M4.35 9.15h4.2"
|
||||
/>
|
||||
<path
|
||||
fill="context-fill"
|
||||
d="M12.1 8.35c1.45 0 2.65 1.15 2.65 2.55v2.1c0 .35-.28.62-.62.62h-.75v1.05c0 .55-.45 1-1 1h-.55c-.55 0-1-.45-1-1v-1.05h-.55c-.35 0-.62-.28-.62-.62v-2.1c0-1.4 1.2-2.55 2.65-2.55z"
|
||||
/>
|
||||
<path
|
||||
fill="context-fill"
|
||||
d="M16.55 9.05c1.05 0 1.9.82 1.9 1.85v1.35c0 1-.85 1.85-1.9 1.85-.35 0-.62-.28-.62-.62v-3.8c0-.35.28-.62.62-.62z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1020 B |
@@ -116,6 +116,69 @@
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<label><html:h2 data-l10n-id="prefs-section-lecture"></html:h2></label>
|
||||
<html:p id="chatpapers-pref-tts-hint" class="chatpapers-pref-hint"></html:p>
|
||||
|
||||
<hbox align="center">
|
||||
<html:label
|
||||
for="chatpapers-pref-tts-provider"
|
||||
data-l10n-id="prefs-tts-provider"
|
||||
></html:label>
|
||||
<html:select id="chatpapers-pref-tts-provider" preference="ttsProvider">
|
||||
</html:select>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center">
|
||||
<html:label
|
||||
for="chatpapers-pref-tts-voice"
|
||||
data-l10n-id="prefs-tts-voice"
|
||||
></html:label>
|
||||
<html:input
|
||||
type="text"
|
||||
id="chatpapers-pref-tts-voice"
|
||||
preference="ttsVoice"
|
||||
></html:input>
|
||||
</hbox>
|
||||
|
||||
<vbox id="chatpapers-pref-piper-box" hidden="true">
|
||||
<hbox align="center">
|
||||
<html:label
|
||||
for="chatpapers-pref-piper-path"
|
||||
data-l10n-id="prefs-piper-path"
|
||||
></html:label>
|
||||
<html:input
|
||||
type="text"
|
||||
id="chatpapers-pref-piper-path"
|
||||
preference="piperPath"
|
||||
></html:input>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<html:label
|
||||
for="chatpapers-pref-piper-model"
|
||||
data-l10n-id="prefs-piper-model"
|
||||
></html:label>
|
||||
<html:input
|
||||
type="text"
|
||||
id="chatpapers-pref-piper-model"
|
||||
preference="piperModelPath"
|
||||
></html:input>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<hbox align="center">
|
||||
<html:label
|
||||
for="chatpapers-pref-mineru-path"
|
||||
data-l10n-id="prefs-mineru-path"
|
||||
></html:label>
|
||||
<html:input
|
||||
type="text"
|
||||
id="chatpapers-pref-mineru-path"
|
||||
preference="mineruPath"
|
||||
></html:input>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<label><html:h2 data-l10n-id="prefs-section-prompts"></html:h2></label>
|
||||
<html:label data-l10n-id="prefs-system-prompt"></html:label>
|
||||
|
||||
@@ -58,3 +58,38 @@ cite-empty = No styles available
|
||||
cite-copied = Bibliography copied
|
||||
cite-exported = Bibliography exported
|
||||
cite-export-cancel = Export cancelled
|
||||
|
||||
item-section-lecture-head = Voice lecture
|
||||
item-section-lecture-sidenav = Voice lecture
|
||||
|
||||
lecture-loading = Loading voice lecture…
|
||||
lecture-mode-label = Voice lecture · Prepare then listen
|
||||
lecture-empty-title = AI lecture mode
|
||||
lecture-empty-desc = One-click prep: overview and paragraph-by-paragraph listening, with typed Q&A and spoken answers.
|
||||
lecture-start = Start preparation
|
||||
lecture-status-idle = Click Start preparation — AI reads the full paper first
|
||||
lecture-status-preparing = Preparing lecture…
|
||||
lecture-status-ready = Lecture ready ✓
|
||||
lecture-status-ready-phase1 = Preparation done (Phase 1: summary ready)
|
||||
lecture-status-ready-step1 = Ready: { $count } segments — tap a segment or press Play
|
||||
lecture-status-failed = Preparation incomplete
|
||||
lecture-beat-list-title = Overview lecture
|
||||
lecture-play-start = Play
|
||||
lecture-play-pause = Pause
|
||||
lecture-play-next = Next
|
||||
lecture-play-prev = Previous
|
||||
lecture-play-complete = Playback finished
|
||||
lecture-beat-tts-pending = Synthesizing
|
||||
lecture-beat-tts-failed = Failed
|
||||
lecture-reprepare = Re-prepare
|
||||
lecture-no-pdf = No PDF attachment on this item
|
||||
lecture-attach-error = Cannot read PDF attachment
|
||||
lecture-mount-error = Failed to load voice lecture pane
|
||||
lecture-platform-hint-mac = macOS: set MinerU path under Preferences → ChatPapers → Voice lecture, or leave empty to use mineru on PATH.
|
||||
lecture-platform-hint-win = Windows: set the full path to mineru.exe under Preferences → ChatPapers → Voice lecture.
|
||||
lecture-platform-hint-other = Configure MinerU path in Preferences to enable structured PDF parsing.
|
||||
|
||||
lecture-tts-provider = TTS: { $provider }
|
||||
lecture-tts-test = Test voice
|
||||
lecture-tts-testing = Synthesizing test speech…
|
||||
lecture-tts-test-done = Speech ready — playing
|
||||
|
||||
@@ -27,3 +27,11 @@ prefs-hint-cloud = Cloud provider: paper text is sent to the selected API endpoi
|
||||
prefs-models-empty = No models returned.
|
||||
prefs-models-pick = Enter a model id from the list (showing up to 30):
|
||||
prefs-privacy = Privacy: ChatPapers only sends content when you click Send/Summarize, and only to the endpoint you configured. API keys are stored in local Zotero preferences.
|
||||
|
||||
prefs-section-lecture = Voice lecture
|
||||
prefs-tts-provider = TTS engine
|
||||
prefs-tts-voice = Voice (optional)
|
||||
prefs-piper-path = Piper executable
|
||||
prefs-piper-model = Piper model path (.onnx)
|
||||
prefs-mineru-path = MinerU path
|
||||
prefs-tts-hint-empty = Choose a TTS engine. Local engines are fully offline — no API key needed.
|
||||
|
||||
@@ -59,3 +59,37 @@ cite-copied = 参考文献已复制到剪贴板
|
||||
cite-exported = 参考文献已导出
|
||||
cite-export-cancel = 已取消导出
|
||||
|
||||
item-section-lecture-head = 语音伴读
|
||||
item-section-lecture-sidenav = 语音伴读
|
||||
|
||||
lecture-loading = 正在加载语音伴读…
|
||||
lecture-mode-label = 语音伴读 · 先备课再听
|
||||
lecture-empty-title = AI 老师式伴读
|
||||
lecture-empty-desc = 一键备课:整体讲解与逐段精读,随时文字提问并获得语音回答。
|
||||
lecture-start = 开始备课
|
||||
lecture-status-idle = 点击「开始备课」,AI 将先读完整篇论文
|
||||
lecture-status-preparing = 正在备课…
|
||||
lecture-status-ready = 老师已备课 ✓
|
||||
lecture-status-ready-phase1 = 备课完成(Phase 1:摘要已生成)
|
||||
lecture-status-ready-step1 = 备课完成:{ $count } 段讲解可播放,点击下方段落或播放按钮开始听课
|
||||
lecture-status-failed = 备课未完成,请重试或检查 LLM 设置
|
||||
lecture-beat-list-title = 整体讲解
|
||||
lecture-play-start = 播放
|
||||
lecture-play-pause = 暂停
|
||||
lecture-play-next = 下一段
|
||||
lecture-play-prev = 上一段
|
||||
lecture-play-complete = 本轮讲解播放完毕
|
||||
lecture-beat-tts-pending = 合成中
|
||||
lecture-beat-tts-failed = 失败
|
||||
lecture-reprepare = 重新备课
|
||||
lecture-no-pdf = 当前条目没有可用的 PDF 附件
|
||||
lecture-attach-error = 无法读取 PDF 附件
|
||||
lecture-mount-error = 语音伴读面板加载失败
|
||||
lecture-platform-hint-mac = macOS:MinerU 路径可在偏好设置 → ChatPapers → 语音伴读 中配置;留空则尝试 PATH 中的 mineru。
|
||||
lecture-platform-hint-win = Windows:请在偏好设置中填写 MinerU 可执行文件完整路径(如 mineru.exe)。
|
||||
lecture-platform-hint-other = 请在偏好设置中配置 MinerU 路径以启用 PDF 结构化解析。
|
||||
|
||||
lecture-tts-provider = TTS 引擎:{ $provider }
|
||||
lecture-tts-test = 试听语音
|
||||
lecture-tts-testing = 正在合成测试语音…
|
||||
lecture-tts-test-done = 语音合成完成,正在播放
|
||||
|
||||
@@ -27,3 +27,11 @@ prefs-hint-cloud = 云端 Provider:论文内容将发送到所选 API 端点
|
||||
prefs-models-empty = 未返回任何模型。
|
||||
prefs-models-pick = 从列表中输入模型 ID(最多显示 30 个):
|
||||
prefs-privacy = 隐私说明:仅在你点击发送/总结时,向你配置的端点发送内容。API Key 仅保存在本地 Zotero 偏好设置中。
|
||||
|
||||
prefs-section-lecture = 语音伴读
|
||||
prefs-tts-provider = TTS 引擎
|
||||
prefs-tts-voice = 音色(可选)
|
||||
prefs-piper-path = Piper 可执行文件
|
||||
prefs-piper-model = Piper 模型路径 (.onnx)
|
||||
prefs-mineru-path = MinerU 路径
|
||||
prefs-tts-hint-empty = 请选择 TTS 引擎。本地引擎完全离线,无需 API Key。
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
"id": "__addonID__",
|
||||
"update_url": "__updateURL__",
|
||||
"strict_min_version": "9.0",
|
||||
"strict_max_version": "9.*"
|
||||
"strict_max_version": "10.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,3 +13,10 @@ pref("systemPrompt", "");
|
||||
pref("summaryPrompt", "");
|
||||
pref("sendMetadata", true);
|
||||
pref("verboseLog", false);
|
||||
pref("ttsProvider", "");
|
||||
pref("ttsApiKey", "");
|
||||
pref("ttsVoice", "");
|
||||
pref("lectureTeacherStyle", "balanced");
|
||||
pref("mineruPath", "");
|
||||
pref("piperPath", "");
|
||||
pref("piperModelPath", "");
|
||||
|
||||
Reference in New Issue
Block a user