Skip to content

Commit

Permalink
feat: Audio clip tool supports text configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
lixinghua123 committed May 13, 2024
1 parent d33ec69 commit 2b3ca11
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ import React, { useState, useEffect, useContext, useMemo } from 'react';
import { Input } from 'antd';
import { useSetState } from 'ahooks';
import { SetState } from 'ahooks/lib/useSetState';
import { IAudioTextToolConfig } from '@labelbee/lb-utils';
import { IAudioTextToolConfig, ITextConfigItem } from '@labelbee/lb-utils';
import styles from './index.module.scss';
export enum EContextType {
before = '前文',
after = '后文',
}

export const DEFAULT_CLIP_TEXT_CONFIG_ITEM = [
{
label: '文本',
key: 'text',
required: false,
default: '',
maxLength: 3000,
},
];

interface IAudioContextProps {
audioContext: {
visible?: boolean;
Expand Down Expand Up @@ -98,6 +108,7 @@ interface IAudioClipState extends IAudioClipConfig {
combined: boolean;
/** 是否按下分割键 */
segment: boolean;
clipTextList: ITextConfigItem[];
}
interface IAudioClipContext {
audioClipState: IAudioClipState;
Expand All @@ -114,6 +125,7 @@ const DEFAULT_AUDIO_CLIP = {
clipTextConfigurable: false,
combined: false,
segment: false,
clipTextList: DEFAULT_CLIP_TEXT_CONFIG_ITEM,
};

const AudioClipContext = React.createContext<IAudioClipContext>({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import AttributeList from '@/components/attributeList';
import { IAudioTimeSlice } from '@labelbee/lb-utils';
import { IAudioTimeSlice, ITextConfigItem } from '@labelbee/lb-utils';
import { EventBus } from '@labelbee/lb-annotation';
import ClipIcon from '@/assets/annotation/audio/clipSmall.svg';
import ClipActiveIcon from '@/assets/annotation/audio/clipASmall.svg';
Expand Down Expand Up @@ -34,6 +34,7 @@ const ClipSidebar = (props: IClipSidebarProps) => {
clipAttributeConfigurable,
secondaryAttributeConfigurable,
subAttributeList,
clipTextList,
} = audioClipState;

const { id: selectedId } = selectedRegion;
Expand Down Expand Up @@ -72,6 +73,17 @@ const ClipSidebar = (props: IClipSidebarProps) => {
}),
];

const showClipText = (region: IAudioTimeSlice) => {
let clipShowText = '';
if (clipTextConfigurable && clipTextList?.length > 0) {
clipTextList.forEach((i: ITextConfigItem, index: number) => {
const segmentSymbol = !clipAttributeConfigurable && index === 0 ? '' : ',';
clipShowText = clipShowText + `${segmentSymbol}${i.label}${region[i.key]}`;
});
}
return clipShowText;
};

return (
<div className={styles.clipSidebar}>
<div className={styles.clipResults}>
Expand All @@ -84,9 +96,7 @@ const ClipSidebar = (props: IClipSidebarProps) => {

const showText = `${
clipAttributeConfigurable ? getAttributeShowText(attribute, list) : ''
}${clipAttributeConfigurable && clipTextConfigurable ? ',' : ''}${
clipTextConfigurable ? `${t('textTool')}${text}` : ''
}`;
}${showClipText(item)}`;
return (
<div
className={classnames({
Expand Down
11 changes: 10 additions & 1 deletion packages/lb-components/src/components/audioAnnotate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import {
} from '@labelbee/lb-annotation';
import styles from './index.module.scss';
import TagResultShow from '@/components/audioAnnotate/tagResultShow';
import { AudioClipProvider, useAudioClipStore } from './audioContext';
import {
AudioClipProvider,
DEFAULT_CLIP_TEXT_CONFIG_ITEM,
useAudioClipStore,
} from './audioContext';
import TextInput from './textInput';
import { connect } from 'react-redux';
import { a2MapStateToProps, IA2MapStateProps } from '@/store/annotation/map';
Expand Down Expand Up @@ -101,6 +105,7 @@ const AudioTextToolTextarea = ({
textConfigurable,
updateRegion,
clipAttributeList,
clipTextList,
}: any) => {
return (
<div className={styles.textareaContainer}>
Expand All @@ -120,6 +125,7 @@ const AudioTextToolTextarea = ({
textConfigurable={textConfigurable}
updateRegion={updateRegion}
clipAttributeList={clipAttributeList}
clipTextList={clipTextList}
/>
</div>
</div>
Expand Down Expand Up @@ -411,6 +417,7 @@ const AudioAnnotate: React.FC<AppProps & IProps> = (props) => {
secondaryAttributeConfigurable = false,
inputList = [],
configList = [],
clipTextList = DEFAULT_CLIP_TEXT_CONFIG_ITEM,
} = useMemo(() => {
if (annotationStepInfo) {
return CommonToolUtils.jsonParser(annotationStepInfo?.config);
Expand All @@ -424,6 +431,7 @@ const AudioAnnotate: React.FC<AppProps & IProps> = (props) => {
clipTextConfigurable,
subAttributeList,
secondaryAttributeConfigurable,
clipTextList,
};

const valid = audioContext ? audioContext?.valid : true;
Expand Down Expand Up @@ -603,6 +611,7 @@ const AudioAnnotate: React.FC<AppProps & IProps> = (props) => {
clipTextConfigurable={clipTextConfigurable}
clipAttributeList={clipAttributeList}
clipAttributeConfigurable={clipAttributeConfigurable}
clipTextList={clipTextList}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@ import React, { FocusEvent, useEffect, useRef, useState } from 'react';
import { Radio, Switch, Tooltip } from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { TextareaWithFooter } from '@/views/MainView/sidebar/TextToolSidebar';
import { DEFAULT_TEXT_CONFIG_ITEM, timeFormat, getAttributeColor, getAttributeFontColor, getAttributeShowText, updateColorOpacity } from '@/utils/audio';
import { cKeyCode } from '@labelbee/lb-annotation'
import {
DEFAULT_TEXT_CONFIG_ITEM,
timeFormat,
getAttributeColor,
getAttributeFontColor,
getAttributeShowText,
updateColorOpacity,
} from '@/utils/audio';
import { cKeyCode } from '@labelbee/lb-annotation';
import { IAudioTimeSlice, ITextConfigItem } from '@labelbee/lb-utils';
import classnames from 'classnames';
import AudioContext, { useAudioClipStore } from '../audioContext';
import AudioContext, { DEFAULT_CLIP_TEXT_CONFIG_ITEM, useAudioClipStore } from '../audioContext';
import styles from './index.module.scss';
import { IInputList } from '@/types/main';
import { useTranslation } from 'react-i18next';
// import { AlgorithmButtonForText } from '../icons/algorithmButton';

const EKeyCode = cKeyCode.default
const EKeyCode = cKeyCode.default;

interface IClearIcon {
onClick: () => void;
Expand Down Expand Up @@ -72,6 +79,7 @@ interface IProps {
/** 更新截取片段数据 */
updateRegion?: (region: IAudioTimeSlice) => void;
isEdit?: boolean;
clipTextList: ITextConfigItem[];
}

export const SingleTextInput = (props: any) => {
Expand All @@ -96,6 +104,7 @@ export const SingleTextInput = (props: any) => {
onFocusStyle = {},
// 右侧输入框上方展示元素
extra,
errorText,
} = props;
const { maxLength } = config;

Expand Down Expand Up @@ -237,6 +246,7 @@ export const SingleTextInput = (props: any) => {
>
<TextareaWithFooter footer={TextareaFooter} textareaProps={textareaProps} />
</div>
{errorText && <span style={{ color: '#ff4d4f', lineHeight: '22px' }}>{errorText}</span>}
</div>
);
};
Expand All @@ -262,6 +272,7 @@ const TextInput = (props: IProps) => {
clipAttributeConfigurable,
updateRegion,
clipAttributeList = [],
clipTextList = DEFAULT_CLIP_TEXT_CONFIG_ITEM,
} = props;

const { t } = useTranslation();
Expand All @@ -273,15 +284,13 @@ const TextInput = (props: IProps) => {
const configList = dataList || [{ ...DEFAULT_TEXT_CONFIG_ITEM }];
let regionsList = regions;


if (clipTextConfigurable && !isCheck) {
const selectedId = audioClipState.selectedRegion.id;
regionsList = regionsList.filter((item) => {
return item.id === selectedId;
});
}


const textareaFocus = (index: number) => {
setTimeout(() => {
const textarea = document.getElementById(`textInput-${index}`) as HTMLTextAreaElement;
Expand Down Expand Up @@ -353,14 +362,7 @@ const TextInput = (props: IProps) => {
});
}

let clipIdMapText: { [key: string]: string } = {};
if (clipTextConfigurable && regionsList) {
regionsList.forEach((item) => {
const { id, text } = item;
clipIdMapText[id] = text;
});
}

const clipTextResult = regionsList[0];
return (
<>
{config?.enablePlaceholderHotkey && (
Expand Down Expand Up @@ -430,13 +432,21 @@ const TextInput = (props: IProps) => {
/>
))}
{clipTextConfigurable &&
regionsList.map((item, index) => {
const { id, start, end, attribute } = item;
regionsList.length > 0 &&
clipTextList.map((item, index) => {
const { id, start, end, attribute } = clipTextResult;
const { maxLength = 3000, label, key, required } = item;
const text = clipTextResult?.[key];
const clipIdMapText = { [clipTextResult.id]: text };

// 兼容SingleTextInput的props
const config = {
label: `${t('textTool')}${timeFormat(start, 'ss.SSS')} - ${timeFormat(end, 'ss.SSS')})`,
label: `${label ?? t('textTool')}${timeFormat(start, 'ss.SSS')} - ${timeFormat(
end,
'ss.SSS',
)})`,
key: id,
maxLength: 3000,
maxLength,
};
// 处理按tab无法正常切换问题
const regionIndex = _configList.length + index;
Expand All @@ -447,6 +457,10 @@ const TextInput = (props: IProps) => {
color: getAttributeFontColor(attribute, clipAttributeList),
backgroundColor: attributeColor,
};
const errorTips = t('LeastCharacterError', {
num: 1,
});
const errorText = required && text.length < 1 ? errorTips : undefined;

return (
<SingleTextInput
Expand All @@ -457,8 +471,8 @@ const TextInput = (props: IProps) => {
result={clipIdMapText}
updateText={(text: string) => {
updateRegion?.({
...item,
text,
...clipTextResult,
[key]: text,
});
}}
switchToNextTextarea={() => {
Expand All @@ -484,6 +498,7 @@ const TextInput = (props: IProps) => {
</div>
) : null
}
errorText={errorText}
/>
);
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import LoopIcon from '@/assets/annotation/audio/loop.svg';
import { Typography } from 'antd';
import { useClickAway } from 'ahooks';
import { classnames } from '@/utils';
import { IAudioTimeSlice } from '@labelbee/lb-utils'
import { IAudioTimeSlice, ITextConfigItem } from '@labelbee/lb-utils';

import styles from './index.module.scss';
import { useTranslation } from 'react-i18next';

interface IProps {
/** 挂载到目标元素 */
Expand All @@ -36,12 +37,14 @@ interface IProps {
const { Paragraph } = Typography;
/** 展示在音频图上的截取片段 */
const ClipRegion = (props: IProps) => {
const { t } = useTranslation();
const { audioClipState, setAudioClipState } = useAudioClipStore();
const {
clipAttributeList,
clipAttributeConfigurable,
clipTextConfigurable,
selectedRegion,
clipTextList,
} = audioClipState;

const ref = useRef(null);
Expand Down Expand Up @@ -116,11 +119,12 @@ const ClipRegion = (props: IProps) => {
</div>
)}

{clipTextConfigurable && (
<Paragraph ellipsis={{ rows: 2 }} className={styles.text} style={textStyle}>
文本:{text}
</Paragraph>
)}
{clipTextConfigurable &&
clipTextList?.map((i: ITextConfigItem, index: number) => (
<Paragraph ellipsis={{ rows: 2 }} className={styles.text} style={textStyle} key={index}>
{i?.label ?? t('textTool')}:{region[i?.key] ?? ''}
</Paragraph>
))}
</div>
);

Expand Down
14 changes: 13 additions & 1 deletion packages/lb-components/src/components/audioPlayer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getWebPcm2WavBase64 } from '@/components/audioAnnotate/utils/getWebPcm2
import _, { debounce, sortBy } from 'lodash';
import { PauseOutlined, CaretRightOutlined } from '@ant-design/icons';
import { cKeyCode, cTool, EventBus, TagUtils } from '@labelbee/lb-annotation';
import { IAudioTimeSlice } from '@labelbee/lb-utils';
import { IAudioTimeSlice,ITextConfigItem } from '@labelbee/lb-utils';
import { Button } from 'antd';
import InvalidPage from '@/components/invalidPage';
import ImageError from '@/components/imageError';
Expand Down Expand Up @@ -86,6 +86,7 @@ export const AudioPlayer = ({
hoverRegionId,
footer,
drawLayerSlot,
clipTextList,
}: {
fileData: any;
height?: number;
Expand Down Expand Up @@ -114,6 +115,7 @@ export const AudioPlayer = ({
hoverRegionId?: string;
footer?: RenderFooter;
drawLayerSlot?: any;
clipTextList: ITextConfigItem[];
}) => {
const { url, path } = fileData;
const [isPlaying, setIsPlaying] = useState<boolean>(false);
Expand Down Expand Up @@ -243,6 +245,7 @@ export const AudioPlayer = ({
clipConfigurable,
secondaryAttributeConfigurable,
subAttributeList,
clipTextList
};

useEffect(() => {
Expand Down Expand Up @@ -558,6 +561,15 @@ export const AudioPlayer = ({
regionItem.subAttribute = defaultSubAttribute ?? {};
}

if (clipTextConfigurable) {
clipTextList.forEach((i, index) => {
if (index === 0) {
Object.assign(regionItem, { text: i?.default });
} else {
Object.assign(regionItem, { [i.key]: i?.default });
}
});
}
updateRegion?.(regionItem);
});

Expand Down
1 change: 1 addition & 0 deletions packages/lb-utils/src/types/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface IAudioTimeSlice {
subAttribute?: {
[key: string]: string;
};
[key: string]: any;
}

export interface ITextConfigItem {
Expand Down

0 comments on commit 2b3ca11

Please sign in to comment.