ReactJS AssemblyAI 演讲者标注转录

问题描述 投票:0回答:1

我想知道如何使用 assemblyai api 端点将说话者标签包含在我的情绪分析应用程序中。我在输出扬声器标签时遇到问题,所以我希望这里有人可以提供帮助。

我在这个应用程序中使用reactjs。致谢:Marius Espajo 作为创建此应用程序的参考。 本教程的 YouTube 链接:https://www.youtube.com/watch?v=OKJiSsBulRo&t=1934s

应用程序.js

import React from 'react';
import {
  Avatar,
  Box,
  Text,
  VStack,
  Grid,
  HStack,
} from '@chakra-ui/react';
import { useState, useEffect } from 'react';
import { Recorder } from 'react-voice-recorder';
import 'react-voice-recorder/dist/index.css';
import axios from 'axios';
import Status from './Status';
import Result from './Result';




const assemblyApi = axios.create({
  baseURL: 'https://api.assemblyai.com/v2',
  headers: {
    authorization: process.env.REACT_APP_ASSEMBLY_API_KEY,
    'content-type': 'application/json',
  },
});

const initialState = {
  url: null,
  blob: null,
  chunks: null,
  duration: {
    h: 0,
    m: 0, 
    s: 0,
  },
};

function App() {
  const [audioDetails, setAudioDetails] = useState(initialState);
  const [transcript, setTranscript] = useState({ id: '' });
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const interval = setInterval(async () => {
      if (transcript.id && transcript.status !== 'completed' && isLoading) {
        try {
          const { data: transcriptData } = await assemblyApi.get(
            `/transcript/${transcript.id}`
          );
          setTranscript({ ...transcript, ...transcriptData }); // have stats = 'completed'
        } catch (err) {
          console.error(err);
        }
      } else {
        setIsLoading(false);
        clearInterval(interval);
      }
    }, 1000);
    return () => clearInterval(interval);
  }, [isLoading, transcript]);

  const handleAudioStop = data => {
    setAudioDetails(data);
  };

  const handleReset = () => {
    setAudioDetails({ ...initialState });
    setTranscript({ id: '' });
  };

  const handleAudioUpload = async (audioFile) => {
    setIsLoading(true);

    const { data: uploadResponse } = await assemblyApi.post('/upload', audioFile);

    const { data } = await assemblyApi.post('/transcript', {
      audio_url: uploadResponse.upload_url,
      speaker_labels: true,
      sentiment_analysis: true,
      entity_detection: true,
      iab_categories: true,
    });

    setTranscript({ id: data.id });
  };
  return (
      <Box textAlign="center" fontSize="xl">
        <Grid
          minH={{ base: '50vh', md: '70vh', lg: '100vh' }}
          p={{ base: '30px', md: '54px', lg: '90px' }}
        >
          <VStack spacing={8}>
            <Avatar
              size="2xl"
              name="Assembly AI"
              src="https://images.unsplash.com/photo-1535378620166-273708d44e4c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=957&q=80"
            />

            <Box>
              {transcript.text && transcript.status === 'completed' ? (
              <Result transcript={transcript} /> 
              ) : (
                <Status isLoading={isLoading} status={transcript.status} />
              )}
            </Box>

            <Box>
              <HStack spacing="15px">
                <Box
                  w={{ base: '13px', md: '15px', lg: '20px' }}
                  h={{ base: '13px', md: '15px', lg: '20px' }}
                  bg="lightgreen">
                </Box>{' '}
                <Text fontSize="sm" pr="-100px">
                  Positive
                </Text>

                <Box
                  w={{ base: '13px', md: '15px', lg: '20px' }}
                  h={{ base: '13px', md: '15px', lg: '20px' }}
                  bg={'lightgray'}>
                </Box>{' '}
                <Text fontSize="sm">Neutral</Text>
                <Box
                  w={{ base: '13px', md: '15px', lg: '20px' }}
                  h={{ base: '13px', md: '15px', lg: '20px' }}
                  bg="pink.200">
                </Box>{' '}
                <Text fontSize="sm">Negative</Text>
              </HStack>
            </Box>

            <Box width={{ base: '300px', md: '360px', lg: '900px' }} pt="-1">
              <Recorder
                record={true}
                audioURL={audioDetails.url}
                handleAudioStop={handleAudioStop}
                handleAudioUpload={handleAudioUpload}
                handleReset={handleReset}
              />
            </Box>
          </VStack>
        </Grid>
      </Box>
  );
}

export default App;

状态.js

import { Text, Progress } from '@chakra-ui/react';

const Status = ({ isLoading, status }) => {
  return (
    <div>
      <Text>
        {isLoading
          ? `Calculating... ${status || 'uploading'}...`
          : 'Give me audio!'}
      </Text>
      <Progress
        size="sm"
        width={ { base: 200, md:300, lg:500}}
        isIndeterminate={isLoading}
        colorScheme="green"
      />
    </div>
  );
};

export default Status;

结果.js

import {Box, Text} from '@chakra-ui/react'
import Highlighted from './Highlighted'

const Result = ({ transcript }) => {
  return (
    <div>
      <Box width={{ base: '300px', md: '700px', lg:'1000px'}} textAlign='justify'>
        <Text fontSize={{ base: '15px', md: '20px', lg: '25px'}}>
            {transcript.sentiment_analysis_results.map(result => (
            <Highlighted text={result.text} sentiment={result.sentiment} />
        ))}
        </Text>
        </Box>
    </div>
  )
}   

export default Result 

突出显示.js

import { Box, Text, Tooltip} from '@chakra-ui/react'

const sentimentColor = {
    POSITIVE: 'lightgreen',
    NEGATIVE: 'pink',
    NEUTRAL: 'lightgray',
};

const Highlighted = ({ text, sentiment}) => {
  return (
    <Box as="mark" bg={sentimentColor[sentiment]} mr="1" textAlign="left"  > {text} </Box>
  )
}

export default Highlighted
javascript reactjs api rest sentiment-analysis
1个回答
0
投票

如果您想查看,我已将扬声器标签示例添加到this存储库。您可以在 API 响应数据中添加新标志,如下所示:

  const { data } = await assemblyAPI.post("/transcript", {
  audio_url: uploadResponse.upload_url,
  //features
  sentiment_analysis: true,
  entity_detection: true,
  iab_categories: true,
  speaker_labels: true,
});

这将允许您检索包含以下信息的“话语”对象:

`utterances:[
    0:{
    confidence:0.9359033333333334,
    end:26950,
    speaker:"A",
    start:250,
    text:"Smoke from hundreds of wildfires in Canada is triggering air qua 
    ...",
    words:[...]`

此外,我还创建了一个用于显示扬声器的新组件:

const Speakers = ({ transcript }) => {
  return (
    <div>
      <h3>Speakers: </h3>
      <div>
        {transcript.utterances.map((utterance) => (
          <div key={utterance.start}>
            <span style={{ fontWeight: "bolder", paddingRight: "8px" }}>
              {utterance.speaker}:
            </span>
            <span>{utterance.text}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Speakers;

有关实现的更多详细信息,您可以查看我的 GitHub 存储库。

© www.soinside.com 2019 - 2024. All rights reserved.