You've already forked bilibili-subtitle
Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b481b8a55a | ||
![]() |
3cede8650d | ||
![]() |
69e0497081 | ||
![]() |
8776186486 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "bilibili-subtitle",
|
"name": "bilibili-subtitle",
|
||||||
"version": "1.11.3",
|
"version": "1.11.5",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "哔哩哔哩字幕列表",
|
"description": "哔哩哔哩字幕列表",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
43
src/components/DebateChat.tsx
Normal file
43
src/components/DebateChat.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { useAppSelector } from '@/hooks/redux';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DebateChat: React.FC<DebateProps> = ({ messages }) => {
|
||||||
|
const fontSize = useAppSelector(state => state.env.envData.fontSize)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col h-full">
|
||||||
|
<div className="flex-1 overflow-y-auto p-4">
|
||||||
|
{messages.map((message, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`flex mb-4 ${
|
||||||
|
message.side === 'pro' ? 'justify-start' : 'justify-end'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`max-w-[85%] rounded-2xl p-3 shadow-md relative ${
|
||||||
|
message.side === 'pro'
|
||||||
|
? 'bg-blue-100 text-blue-800 ml-2'
|
||||||
|
: 'bg-green-100 text-green-800 mr-2'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<p className={`${fontSize === 'large' ? 'text-sm' : 'text-xs'} font-bold mb-1`}>
|
||||||
|
{message.side === 'pro' ? '正方' : '反方'}
|
||||||
|
</p>
|
||||||
|
<p className={fontSize === 'large' ? 'text-sm' : 'text-xs'}>{message.content}</p>
|
||||||
|
<div
|
||||||
|
className={`absolute w-4 h-4 ${
|
||||||
|
message.side === 'pro'
|
||||||
|
? 'bg-blue-100 -left-2 top-2 rounded-bl-full'
|
||||||
|
: 'bg-green-100 -right-2 top-2 rounded-br-full'
|
||||||
|
}`}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DebateChat;
|
@@ -245,7 +245,7 @@ const MoreBtn = (props: Props) => {
|
|||||||
下载音频(m4s)
|
下载音频(m4s)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className='hover:bg-accent'>
|
{/* <li className='hover:bg-accent'>
|
||||||
<a className='flex items-center' onClick={(e) => {
|
<a className='flex items-center' onClick={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
@@ -264,7 +264,7 @@ const MoreBtn = (props: Props) => {
|
|||||||
<AiFillWechat className='w-[20px] h-[20px] text-primary/75 bg-white rounded-sm p-0.5'/>
|
<AiFillWechat className='w-[20px] h-[20px] text-primary/75 bg-white rounded-sm p-0.5'/>
|
||||||
微信公众号(IndieKKY)
|
微信公众号(IndieKKY)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li> */}
|
||||||
{/* <li className='hover:bg-accent'> */}
|
{/* <li className='hover:bg-accent'> */}
|
||||||
{/* <a className='flex items-center' onClick={(e) => { */}
|
{/* <a className='flex items-center' onClick={(e) => { */}
|
||||||
{/* e.preventDefault() */}
|
{/* e.preventDefault() */}
|
||||||
@@ -297,6 +297,17 @@ const MoreBtn = (props: Props) => {
|
|||||||
选项
|
选项
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{/* 官网 */}
|
||||||
|
<li className='hover:bg-accent'>
|
||||||
|
<a className='flex items-center' onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
openUrl('https://www.bibijun.cc')
|
||||||
|
}}>
|
||||||
|
<img alt='哔哔君' src='/favicon-128x128.png' className='w-[20px] h-[20px] bg-white rounded-sm p-0.5'/>
|
||||||
|
🏠 哔哔君官网
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Popover>}
|
</Popover>}
|
||||||
</>
|
</>
|
||||||
|
@@ -2,7 +2,7 @@ import React, {MutableRefObject, useCallback, useEffect, useMemo, useRef} from '
|
|||||||
import {useAppDispatch, useAppSelector} from '../hooks/redux'
|
import {useAppDispatch, useAppSelector} from '../hooks/redux'
|
||||||
import {setFloatKeyPointsSegIdx, setSegmentFold, setTempData} from '../redux/envReducer'
|
import {setFloatKeyPointsSegIdx, setSegmentFold, setTempData} from '../redux/envReducer'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import {FaClipboardList} from 'react-icons/fa'
|
import {FaClipboardList, FaComments} from 'react-icons/fa'
|
||||||
import {PAGE_MAIN, PAGE_SETTINGS, SUMMARIZE_THRESHOLD, SUMMARIZE_TYPES} from '../consts/const'
|
import {PAGE_MAIN, PAGE_SETTINGS, SUMMARIZE_THRESHOLD, SUMMARIZE_TYPES} from '../consts/const'
|
||||||
import useTranslate from '../hooks/useTranslate'
|
import useTranslate from '../hooks/useTranslate'
|
||||||
import {BsDashSquare, BsPlusSquare, CgFileDocument, FaQuestion, GrOverview, RiFileCopy2Line} from 'react-icons/all'
|
import {BsDashSquare, BsPlusSquare, CgFileDocument, FaQuestion, GrOverview, RiFileCopy2Line} from 'react-icons/all'
|
||||||
@@ -12,6 +12,7 @@ import {useInViewport} from 'ahooks'
|
|||||||
import SegmentItem from './SegmentItem'
|
import SegmentItem from './SegmentItem'
|
||||||
import {stopPopFunc} from '../utils/util'
|
import {stopPopFunc} from '../utils/util'
|
||||||
import useSubtitle from '../hooks/useSubtitle'
|
import useSubtitle from '../hooks/useSubtitle'
|
||||||
|
import DebateChat from './DebateChat'
|
||||||
|
|
||||||
const SummarizeItemOverview = (props: {
|
const SummarizeItemOverview = (props: {
|
||||||
segment: Segment
|
segment: Segment
|
||||||
@@ -113,6 +114,8 @@ const Summarize = (props: {
|
|||||||
<div className={classNames('font-normal', fontSize === 'large' ? 'text-sm' : 'text-xs')}>{question.a}</div>
|
<div className={classNames('font-normal', fontSize === 'large' ? 'text-sm' : 'text-xs')}>{question.a}</div>
|
||||||
</div>)}
|
</div>)}
|
||||||
</div>}
|
</div>}
|
||||||
|
{summary?.type === 'debate' && (summary.content != null) &&
|
||||||
|
<DebateChat messages={summary.content} />}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col justify-center items-center'>
|
<div className='flex flex-col justify-center items-center'>
|
||||||
{segment.text.length < SUMMARIZE_THRESHOLD && <div className='desc-lighter text-xs'>文字过短,无法总结.</div>}
|
{segment.text.length < SUMMARIZE_THRESHOLD && <div className='desc-lighter text-xs'>文字过短,无法总结.</div>}
|
||||||
@@ -200,6 +203,12 @@ const SegmentCard = (props: {
|
|||||||
}))
|
}))
|
||||||
}, [dispatch])
|
}, [dispatch])
|
||||||
|
|
||||||
|
const onSelDebate = useCallback(() => {
|
||||||
|
dispatch(setTempData({
|
||||||
|
curSummaryType: 'debate'
|
||||||
|
}))
|
||||||
|
}, [dispatch])
|
||||||
|
|
||||||
return <div
|
return <div
|
||||||
className={classNames('border border-base-300 bg-base-200/25 rounded flex flex-col m-1.5 p-1.5 gap-1 shadow', showCurrent && 'shadow-primary')}>
|
className={classNames('border border-base-300 bg-base-200/25 rounded flex flex-col m-1.5 p-1.5 gap-1 shadow', showCurrent && 'shadow-primary')}>
|
||||||
<div className='relative flex justify-center min-h-[20px]'>
|
<div className='relative flex justify-center min-h-[20px]'>
|
||||||
@@ -215,6 +224,7 @@ const SegmentCard = (props: {
|
|||||||
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'overview' && 'tab-active')} onClick={onSelOverview}><GrOverview/>概览</a>
|
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'overview' && 'tab-active')} onClick={onSelOverview}><GrOverview/>概览</a>
|
||||||
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'keypoint' && 'tab-active')} onClick={onSelKeypoint}><FaClipboardList/>要点</a>
|
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'keypoint' && 'tab-active')} onClick={onSelKeypoint}><FaClipboardList/>要点</a>
|
||||||
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'question' && 'tab-active')} onClick={onSelQuestion}><FaQuestion/>问题</a>
|
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'question' && 'tab-active')} onClick={onSelQuestion}><FaQuestion/>问题</a>
|
||||||
|
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'debate' && 'tab-active')} onClick={onSelDebate}><FaComments/>辩论</a>
|
||||||
<a className="tab tab-lifted tab-xs tab-disabled cursor-default"></a>
|
<a className="tab tab-lifted tab-xs tab-disabled cursor-default"></a>
|
||||||
</div>}
|
</div>}
|
||||||
<div
|
<div
|
||||||
|
@@ -11,6 +11,7 @@ export const PROMPT_TYPE_TRANSLATE = 'translate'
|
|||||||
export const PROMPT_TYPE_SUMMARIZE_OVERVIEW = 'summarize_overview'
|
export const PROMPT_TYPE_SUMMARIZE_OVERVIEW = 'summarize_overview'
|
||||||
export const PROMPT_TYPE_SUMMARIZE_KEYPOINT = 'summarize_keypoint'
|
export const PROMPT_TYPE_SUMMARIZE_KEYPOINT = 'summarize_keypoint'
|
||||||
export const PROMPT_TYPE_SUMMARIZE_QUESTION = 'summarize_question'
|
export const PROMPT_TYPE_SUMMARIZE_QUESTION = 'summarize_question'
|
||||||
|
export const PROMPT_TYPE_SUMMARIZE_DEBATE = 'summarize_debate'
|
||||||
export const PROMPT_TYPE_SUMMARIZE_BRIEF = 'summarize_brief'
|
export const PROMPT_TYPE_SUMMARIZE_BRIEF = 'summarize_brief'
|
||||||
export const PROMPT_TYPE_ASK = 'ask'
|
export const PROMPT_TYPE_ASK = 'ask'
|
||||||
export const PROMPT_TYPES = [{
|
export const PROMPT_TYPES = [{
|
||||||
@@ -28,6 +29,9 @@ export const PROMPT_TYPES = [{
|
|||||||
}, {
|
}, {
|
||||||
name: '问题',
|
name: '问题',
|
||||||
type: PROMPT_TYPE_SUMMARIZE_QUESTION,
|
type: PROMPT_TYPE_SUMMARIZE_QUESTION,
|
||||||
|
}, {
|
||||||
|
name: '辩论',
|
||||||
|
type: PROMPT_TYPE_SUMMARIZE_DEBATE,
|
||||||
}, {
|
}, {
|
||||||
name: '提问',
|
name: '提问',
|
||||||
type: PROMPT_TYPE_ASK,
|
type: PROMPT_TYPE_ASK,
|
||||||
@@ -58,6 +62,12 @@ export const SUMMARIZE_TYPES = {
|
|||||||
downloadName: '💡常见问题💡',
|
downloadName: '💡常见问题💡',
|
||||||
promptType: PROMPT_TYPE_SUMMARIZE_QUESTION,
|
promptType: PROMPT_TYPE_SUMMARIZE_QUESTION,
|
||||||
},
|
},
|
||||||
|
debate: {
|
||||||
|
name: '辩论',
|
||||||
|
desc: '辩论',
|
||||||
|
downloadName: '💡辩论💡',
|
||||||
|
promptType: PROMPT_TYPE_SUMMARIZE_DEBATE,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PROMPT_DEFAULTS = {
|
export const PROMPT_DEFAULTS = {
|
||||||
@@ -175,6 +185,42 @@ Provide an example to illustrate the expected output:
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
`,
|
||||||
|
[PROMPT_TYPE_SUMMARIZE_DEBATE]: `You are a helpful assistant skilled at generating debates based on video subtitles.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The video's title: '''{{title}}'''.
|
||||||
|
The video's subtitles:
|
||||||
|
|
||||||
|
'''
|
||||||
|
{{segment}}
|
||||||
|
'''
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
Please play the roles of both the affirmative and negative sides to discuss the author's viewpoint.
|
||||||
|
The conversation should consist of 10 rounds(5 sentences from the affirmative side, 5 sentences from the negative side.).
|
||||||
|
The tone should be straightforward.
|
||||||
|
|
||||||
|
Answer in language '{{language}}'.
|
||||||
|
|
||||||
|
## Output format
|
||||||
|
|
||||||
|
Provide an example to illustrate the expected output:
|
||||||
|
|
||||||
|
\`\`\`json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"side": "pro",
|
||||||
|
"content": "xxx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"side": "con",
|
||||||
|
"content": "xxx"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
\`\`\`
|
||||||
`,
|
`,
|
||||||
[PROMPT_TYPE_ASK]: `You are a helpful assistant who answers question related to video subtitles.
|
[PROMPT_TYPE_ASK]: `You are a helpful assistant who answers question related to video subtitles.
|
||||||
Answer in language '{{language}}'.
|
Answer in language '{{language}}'.
|
||||||
|
11
src/typings.d.ts
vendored
11
src/typings.d.ts
vendored
@@ -151,4 +151,13 @@ interface BriefSummary extends Summary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SummaryStatus = 'init' | 'pending' | 'done'
|
type SummaryStatus = 'init' | 'pending' | 'done'
|
||||||
type SummaryType = 'overview' | 'keypoint' | 'brief' | 'question'
|
type SummaryType = 'overview' | 'keypoint' | 'brief' | 'question' | 'debate'
|
||||||
|
|
||||||
|
interface DebateMessage {
|
||||||
|
side: 'pro' | 'con';
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DebateProps {
|
||||||
|
messages: DebateMessage[];
|
||||||
|
}
|
||||||
|
@@ -81,6 +81,9 @@ export const isSummaryEmpty = (summary: Summary) => {
|
|||||||
} else if (summary.type === 'question') {
|
} else if (summary.type === 'question') {
|
||||||
const content: any[] = summary.content??[]
|
const content: any[] = summary.content??[]
|
||||||
return content.length === 0
|
return content.length === 0
|
||||||
|
} else if (summary.type === 'debate') {
|
||||||
|
const content: Array<{ side: string, content: string }> = summary.content ?? []
|
||||||
|
return content.length === 0
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -107,7 +110,12 @@ export const getSummaryStr = (summary: Summary) => {
|
|||||||
s += content.map(item => {
|
s += content.map(item => {
|
||||||
return item.q + '\n' + item.a + '\n'
|
return item.q + '\n' + item.a + '\n'
|
||||||
}).join('\n')
|
}).join('\n')
|
||||||
}
|
} else if (summary.type === 'debate') {
|
||||||
|
const content: Array<{ side: string, content: string }> = summary.content ?? []
|
||||||
|
s += content.map(item => {
|
||||||
|
return (item.side === 'pro'?'正方:':'反方:') + item.content + '\n'
|
||||||
|
}).join('\n')
|
||||||
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user