2017-10-09 1 views
8

Mit Go, ich bin ein RTMP-Stream nehmen, um es zu FLAC Umcodieren (ffmpeg verwenden) und dem Versuch, auf dem Google-Speech API streamen das Audio transkribieren. Ich bekomme jedoch immer EOF Fehler beim Senden der Daten. Ich kann keine Informationen zu diesem Fehler in den Dokumenten finden, so dass ich nicht genau weiß, was das verursacht.Google Speech - Streaming anfordern Gibt EOF Fehler

Ich Chunking die empfangenen Daten in 3s Clips (Länge so lange nicht relevant, da es weniger als die maximale Länge einer Streaming-Erkennungs Anfrage). Hier

ist der Kern meiner Code:

func main() { 

    done := make(chan os.Signal) 
    received := make(chan []byte) 

    go receive(received) 
    go transcribe(received) 

    signal.Notify(done, os.Interrupt, syscall.SIGTERM) 

    select { 
    case <-done: 
     os.Exit(0) 
    } 
} 

func receive(received chan<- []byte) { 
    var b bytes.Buffer 
    stdout := bufio.NewWriter(&b) 

    cmd := exec.Command("ffmpeg", "-i", "rtmp://127.0.0.1:1935/live/key", "-f", "flac", "-ar", "16000", "-") 
    cmd.Stdout = stdout 

    if err := cmd.Start(); err != nil { 
     log.Fatal(err) 
    } 

    duration, _ := time.ParseDuration("3s") 
    ticker := time.NewTicker(duration) 

    for { 
     select { 
     case <-ticker.C: 
      stdout.Flush() 
      log.Printf("Received %d bytes", b.Len()) 
      received <- b.Bytes() 
      b.Reset() 
     } 
    } 
} 

func transcribe(received <-chan []byte) { 
    ctx := context.TODO() 

    client, err := speech.NewClient(ctx) 
    if err != nil { 
     log.Fatal(err) 
    } 

    stream, err := client.StreamingRecognize(ctx) 
    if err != nil { 
     log.Fatal(err) 
    } 

    // Send the initial configuration message. 
    if err = stream.Send(&speechpb.StreamingRecognizeRequest{ 
     StreamingRequest: &speechpb.StreamingRecognizeRequest_StreamingConfig{ 
      StreamingConfig: &speechpb.StreamingRecognitionConfig{ 
       Config: &speechpb.RecognitionConfig{ 
        Encoding:  speechpb.RecognitionConfig_FLAC, 
        LanguageCode: "en-GB", 
        SampleRateHertz: 16000, 
       }, 
      }, 
     }, 
    }); err != nil { 
     log.Fatal(err) 
    } 

    for { 
     select { 
     case data := <-received: 
      if len(data) > 0 { 
       log.Printf("Sending %d bytes", len(data)) 
       if err := stream.Send(&speechpb.StreamingRecognizeRequest{ 
        StreamingRequest: &speechpb.StreamingRecognizeRequest_AudioContent{ 
         AudioContent: data, 
        }, 
       }); err != nil { 
        log.Printf("Could not send audio: %v", err) 
       } 
      } 
     } 
    } 
} 

Ausführen dieses Codes gibt diese Ausgabe:

2017/10/09 16:05:00 Received 191704 bytes 
2017/10/09 16:05:00 Saving 191704 bytes 
2017/10/09 16:05:00 Sending 191704 bytes 
2017/10/09 16:05:00 Could not send audio: EOF 

2017/10/09 16:05:03 Received 193192 bytes 
2017/10/09 16:05:03 Saving 193192 bytes 
2017/10/09 16:05:03 Sending 193192 bytes 
2017/10/09 16:05:03 Could not send audio: EOF 

2017/10/09 16:05:06 Received 193188 bytes 
2017/10/09 16:05:06 Saving 193188 bytes 
2017/10/09 16:05:06 Sending 193188 bytes // Notice that this doesn't error 

2017/10/09 16:05:09 Received 191704 bytes 
2017/10/09 16:05:09 Saving 191704 bytes 
2017/10/09 16:05:09 Sending 191704 bytes 
2017/10/09 16:05:09 Could not send audio: EOF 

Beachten Sie, dass nicht alle der Send s scheitern. hier

Könnte jemand mich in die richtige Richtung? Hat es etwas mit den FLAC-Headern zu tun? Ich frage mich auch, ob vielleicht die Puffer Zurücksetzen verursacht einen Teil der Daten gelöscht werden (das heißt es ist eine nicht-triviale Operation, die tatsächlich einige Zeit in Anspruch nimmt) und es nicht wie diese fehlenden Informationen?

Jeder würde Hilfe wirklich zu schätzen.

+1

Dies ist ein total zufällig, aber haben Sie versucht, es mit dem Rennen Detektor läuft? Es wird wahrscheinlich nichts zeigen, aber Sie wissen nie ... –

+0

@MiloChristiansen guten Ruf! Es gibt eine Wettlaufbedingung. Ich habe versucht, eine thread-sichere Version von 'bufio.Writer' zu erstellen, aber die Bibliothek verwendet' ReadFrom', das kontinuierlich vom Lesegerät liest. Es gibt die Sperre nur frei, wenn alles gelesen wurde: - / – Josh

Antwort

7

Es stellt sich also heraus, dass es eine Möglichkeit gibt, mehr Informationen über den Status des Streams zu erhalten, so dass wir uns nicht nur auf den zurückgegebenen Fehler verlassen müssen.

if err := stream.Send(&speechpb.StreamingRecognizeRequest{ 
    StreamingRequest: &speechpb.StreamingRecognizeRequest_AudioContent{ 
     AudioContent: data, 
    }, 
}); err != nil { 
    resp, err := stream.Recv() 
    log.Printf("Could not send audio: %v", resp.GetError()) 
} 

Diese Drucke:

2017/10/16 17:14:53 Could not send audio: code:3 message:"Invalid audio content: too long." 

, die eine weitaus hilfreiche Fehlermeldung! obwohl