브라우저에서 호스팅된 오디오 스트림 가져오기

오늘은 URL에서 오디오 스트림을 가져오고, 스트림 데이터를 Deepgram으로 보내고, 그 대가로 전사를 받는 방법을 살펴보겠습니다. 이는 라이브 스트림 데이터를 가져와서 실시간으로 전송하려는 경우(또한 실시간 청크로 Deepgram에서 전사를 다시 수신하려는 경우)에 특히 유용합니다.

이를 위해서는 세 가지 주요 단계가 필요합니다.
  • Deepgram에 대한 WebSocket 채널 열기
  • 스트림이 호스팅되는 URL에서 호스팅된 오디오 스트림 데이터를 요청합니다(Fetch 사용)
  • .
  • 증분 청크로 스트림을 Deepgram에 전달합니다
  • .

    Deepgram의 Speech-to-Text API로 녹음된 오디오 스트림을 보려면 무료 계정에 가입하고 API 키here를 받는 것이 좋습니다.

    WebSocket 채널 열기



    가장 먼저 해야 할 일은 브라우저 WebSocket으로 Deepgram에 연결하는 것입니다.

    const socket = new WebSocket('wss://api.deepgram.com/v1/listen', [
      'token',
      'YOUR_DEEPGRAM_API_KEY',
    ])
    


    다음으로 여러 이벤트 리스너를 작성합니다. 이벤트는 프로그래밍된 시스템 내에서 발생하는 동작입니다. 시스템은 이러한 이벤트에 대한 반응으로 코드를 작성할 수 있도록 이러한 이벤트를 알려주도록 설계되었습니다. WebSocket API에는 소켓 열기, 데이터 수신 및 소켓 닫기 프로세스 전체에서 실행되는 여러 이벤트가 포함되어 있습니다. 이벤트 리스너를 사용하여 해당 이벤트에 반응합니다.
    onopen 이벤트가 발생할 때까지 리스닝할 수 있기 때문에 이 WebSocket 로직을 먼저 작성하고 이벤트가 발생하면 오디오 파일을 수신하기 위해 가져오기 요청을 합니다.

    socket.onopen = () => {
      // Fetch stream
      // Send stream to Deepgram
    }
    
    socket.onmessage = (message) => {
      // Receive transcript from Deepgram
      // Do something with transcript
    }
    
    socket.onclose = () => {
      console.log({ event: 'onclose' })
    }
    
    socket.onerror = (error) => {
      console.log({ event: 'onerror', error })
    }
    


    호스팅된 오디오 스트림 가져오기



    다음 단계는 가져오기 요청을 작성하는 것입니다. 브라우저의 전역fetch() 메서드는 요청을 만들 URL인 문자열 매개변수를 사용합니다.

    메서드는 약속을 반환하므로 응답을 기다리고 응답 본문을 가져오기 위해 연결.then()할 수 있습니다.

    socket.onopen = () => {
      const url =
        'https://stream.live.vc.bbcmedia.co.uk/bbc_radio_fourlw_online_nonuk'
    
      fetch(url)
        .then((response) => response.body)
        .then((body) => {
          // Send stream to Deepgram
        })
    }
    


    청크를 읽고 Deepgram으로 보내기



    URL에서 수신한 response.body는 "읽을 수 있는 바이트 데이터 스트림"( Mozilla )인 ReadableStream 입니다. 이것은 단지 읽을 수 있는 데이터라는 것을 의미합니다. 그리고 데이터를 읽으려면 데이터를 분해해야 합니다. 인간이 의미를 이해하기 위해 문장을 단어로 분해해야 하는 방식과 유사합니다.

    스트림 데이터를 어떻게 분해합니까? Streams API는 이러한 목적으로 만들어졌습니다. 이를 사용하여 스트림을 가져오고 스트림에 쓰거나 스트림에서 읽는 단일 데이터 조각인 청크로 분할합니다.

    읽을 수 있는 스트림을 소비하고 이를 청크로 변환하여 Deepgram으로 보내는 함수를 작성할 수 있습니다. 이를 수행하는 방법에는 여러 가지가 있지만 모두 다음을 수행해야 합니다.
  • getReader() 메서드를 사용하여 reader을 생성합니다
  • .
  • 판독기 인터페이스의 read() 메서드를 사용하여 대기열의 각 청크에 대한 액세스 권한을 얻습니다(약속으로 반환됨)

  • 다음은 이 함수를 작성하는 한 가지 방법입니다.

    async function readAllChunks(readableStream) {
      // Create reader:
      const reader = readableStream.getReader()
      while (true) {
        // Read chunks:
        const { done, value } = await reader.read()
        if (done) {
          break
        }
        // Send chunks to Deepgram:
        socket.send(value)
      }
    }
    

    .read() 메서드는 객체로 확인되는 약속을 반환하므로 해당 객체를 donevalue 의 두 속성으로 분해할 수 있습니다. 그런 다음 전사를 위해 해당 값을 Deepgram으로 보낼 수 있습니다.

    Streams API 사양은 ReadableStream를 사용하는 방법에 대해 other useful examples을 제공합니다.

    이제 스트림을 청크로 읽는 논리가 있으므로 함수를 호출하고 읽을 수 있는 스트림을 전달해야 합니다.

    socket.onopen = () => {
      const url =
        'https://stream.live.vc.bbcmedia.co.uk/bbc_radio_fourlw_online_nonuk'
    
      fetch(url)
        .then((response) => response.body)
        .then((body) => {
          // Invoke function that sends readable stream:
          readAllChunks(body)
        })
    }
    


    마무리



    우리는 호스팅된 오디오 스트림을 가져와서 Deepgram으로 보내 실시간으로 전사하는 작업을 수행했습니다. 성적표가 반환되면 우리가 의도한 대로 무엇이든 할 수 있습니다.

    전체 코드는 다음과 같습니다. 또한 스트림의 텍스트를 브라우저 페이지에 넣는 Stackblitz 계정에 an example을 포함시켰습니다. 작동하려면 API 키를 추가해야 합니다.

    const socket = new WebSocket('wss://api.deepgram.com/v1/listen', [
      'token',
      'YOUR_DEEPGRAM_API_KEY',
    ])
    
    socket.onopen = () => {
      const url =
        'https://stream.live.vc.bbcmedia.co.uk/bbc_radio_fourlw_online_nonuk'
      fetch(url)
        .then((response) => response.body)
        .then((body) => {
          readAllChunks(body)
        })
    }
    
    async function readAllChunks(readableStream) {
      const reader = readableStream.getReader()
      while (true) {
        const { done, value } = await reader.read()
        if (done) {
          break
        }
        socket.send(value)
      }
    }
    
    socket.onmessage = (message) => {
      const received = JSON.parse(message.data)
      const transcript = received.channel.alternatives[0].transcript
      if (transcript && received.is_final) {
        document.querySelector('#captions').textContent += transcript + ' '
      }
    }
    
    socket.onclose = () => {
      console.log({ event: 'onclose' })
    }
    
    socket.onerror = (error) => {
      console.log({ event: 'onerror', error })
    }
    


    질문이 있으신가요? 기꺼이 도와드리겠습니다.

    좋은 웹페이지 즐겨찾기