stream सी#- आरटीपी स्ट्रीम कैप्चर करें और भाषण मान्यता को भेजें




ffmpeg speech-recognition (3)

यह एक पुरानी धागा है, लेकिन मैं उस प्रोजेक्ट के लिए उपयोगी था जिस पर मैं काम कर रहा था। लेकिन, मेरे पास वही समस्याएं थीं जैसे कुछ अन्य लोगों ने विंडोज़ पीसी के साथ डीग्रीहिक कोड को स्रोत के रूप में इस्तेमाल करने की कोशिश की।

निम्नलिखित मानकों का उपयोग करके कोड में उस 0 परिवर्तनों के साथ काम करने वाले एफएफएमपीएग समझे:

ffmpeg -ac 1 -f dshow -i audio="{recording device}" -ar 16000 -acodec pcm_s16le -f rtp rtp://{hostname}:{port}

मेरे मामले में, रिकॉर्डिंग डिवाइस नाम "माइक्रोफोन (रियलटेक हाई डेफिनेशन ऑडिओ) था", लेकिन मैंने रिकॉर्डिंग डिवाइस का नाम प्राप्त करने के लिए निम्न का उपयोग किया था:

ffmpeg -list_devices true -f dshow -i dummy

मैं क्या करने की कोशिश कर रहा हूं:

  • सी # में आरटीपी स्ट्रीम कैप्चर करें
  • सिस्टम को उस धारा को अग्रेषित करें। स्पीच.SpeechRecognitionEngine

मैं एक लिनक्स-आधारित रोबोट का निर्माण कर रहा हूं जो माइक्रोफ़ोन इनपुट लेगा, इसे विंडोज मशीन भेजें, जो माइक्रोसॉफ्ट स्पीच रिकग्निशन का उपयोग करते हुए ऑडियो पर कार्रवाई करेगा और रोबोट को जवाब वापस भेज देगा। रोबोट सर्वर से सैकड़ों मील की दूरी पर हो सकता है, इसलिए मैं इंटरनेट पर यह करना चाहता हूं।

मैंने अब तक क्या किया है:

  • रोबोट एमपी 3 प्रारूप में एन्कोडेड एक आरटीपी स्ट्रीम उत्पन्न करता है (अन्य फॉर्मेट उपलब्ध हैं) एफएफएमपीईजी (रोबोट एक रास्पबेरी पाई चल रहे आर्क लिनक्स पर चल रहा है)
  • VLC ActiveX नियंत्रण का उपयोग करते हुए क्लाइंट कंप्यूटर पर स्ट्रीम कैप्चर किया गया
  • पाया गया कि SpeechRecognitionEngine में उपलब्ध विधियां हैं:
    1. recognizer.SetInputToWaveStream ()
    2. recognizer.SetInputToAudioStream ()
    3. recognizer.SetInputToDefaultAudioDevice ()
  • ऐप्प के आउटपुट को लाइन-इन में भेजने के लिए जैक का इस्तेमाल करने पर देखा, लेकिन इसके द्वारा पूरी तरह से भ्रमित किया गया था।

मुझे किसके साथ मदद चाहिए:

मैं वास्तव में वीएलसी से भाषण RECognitionEngine तक स्ट्रीम को कैसे प्रसारित करने के बारे में सोच रहा हूं। वीएलसी स्ट्रीम को बिल्कुल भी उजागर नहीं करता है क्या ऐसा कोई रास्ता है जो मैं सिर्फ एक धारा को पकड़ सकता हूं और उस प्रवाह वस्तु को भाषण मान्यता पहचान में पास कर सकता हूं? या क्या यहां समाधान नहीं है?

आपकी सहायता के लिये पहले से ही धन्यवाद।


बहुत काम करने के बाद, मुझे अंततः Microsoft.SpeechRecognitionEngine मिल गया। स्पीच रीग्निग्निशन एन्जिन एक वावे ऑडियो स्ट्रीम को स्वीकार करने के लिए। यहां प्रक्रिया है:

Pi पर, मेरे पास ffmpeg चल रहा है मैं इस आदेश का उपयोग करते हुए ऑडियो स्ट्रीम करता हूं

ffmpeg -ac 1 -f alsa -i hw:1,0 -ar 16000 -acodec pcm_s16le -f rtp rtp://XXX.XXX.XXX.XXX:1234

सर्वर साइड पर, मैं एक UDPClient बना रहा UDPClient और पोर्ट 1234 पर सुनता हूं। मुझे एक अलग धागे पर पैकेट प्राप्त होता है। सबसे पहले, मैं आरटीपी हेडर ( हेडर प्रारूप समझाया ) को छूटे और एक विशेष धारा में पेलोड लिखूंगा। मुझे स्पीचराइग्निशनइंजिन के लिए कार्य करने के क्रम में सीन की प्रतिक्रिया में वर्णित SpeechStreamer वर्ग का उपयोग करना था यह एक मानक Memory Stream साथ काम नहीं कर रहा था

केवल भाषण मान्यता पक्ष पर जो कुछ भी करना था, वह डिफ़ॉल्ट ऑडियो डिवाइस के बजाय ऑडियो स्ट्रीम में इनपुट सेट करता था

recognizer.SetInputToAudioStream( rtpClient.AudioStream,
    new SpeechAudioFormatInfo(WAVFile.SAMPLE_RATE, AudioBitsPerSample.Sixteen, AudioChannel.Mono));

मैंने इस पर व्यापक परीक्षण नहीं किया है (यानी यह दिनों के लिए स्ट्रीम दे रहा है और अगर यह अभी भी काम करता है तो देख रहा है), लेकिन मैं SpeechRecognized में ऑडियो नमूना को सहेजने में सक्षम SpeechRecognized और यह महान लगता है। मैं 16 KHz की एक नमूना दर का उपयोग कर रहा हूँ मैं डेटा ट्रांसफर की मात्रा को कम करने के लिए नीचे 8 किलोहर्ट्ज़ तक टक्कर लूँगा, लेकिन मैं इसके बारे में चिंता करूंगा कि एक बार यह एक समस्या बन जाए।

मुझे यह भी उल्लेख करना चाहिए, प्रतिक्रिया बहुत तेजी से है मैं एक पूरे वाक्य बोल सकता हूं और एक सेकंड से भी कम समय में प्रतिक्रिया प्राप्त कर सकता हूं। आरटीपी कनेक्शन प्रक्रिया को बहुत कम उपरि जोड़ता है। मुझे एक बेंचमार्क की कोशिश करनी पड़ेगी और बस एमआईसी इनपुट का उपयोग करने के साथ इसकी तुलना करना होगा

संपादित करें: यहां मेरा RTPClient वर्ग है I

    /// <summary>
    /// Connects to an RTP stream and listens for data
    /// </summary>
    public class RTPClient
    {
        private const int AUDIO_BUFFER_SIZE = 65536;

        private UdpClient client;
        private IPEndPoint endPoint;
        private SpeechStreamer audioStream;
        private bool writeHeaderToConsole = false;
        private bool listening = false;
        private int port;
        private Thread listenerThread; 

        /// <summary>
        /// Returns a reference to the audio stream
        /// </summary>
        public SpeechStreamer AudioStream
        {
            get { return audioStream; }
        }
        /// <summary>
        /// Gets whether the client is listening for packets
        /// </summary>
        public bool Listening
        {
            get { return listening; }
        }
        /// <summary>
        /// Gets the port the RTP client is listening on
        /// </summary>
        public int Port
        {
            get { return port; }
        }

        /// <summary>
        /// RTP Client for receiving an RTP stream containing a WAVE audio stream
        /// </summary>
        /// <param name="port">The port to listen on</param>
        public RTPClient(int port)
        {
            Console.WriteLine(" [RTPClient] Loading...");

            this.port = port;

            // Initialize the audio stream that will hold the data
            audioStream = new SpeechStreamer(AUDIO_BUFFER_SIZE);

            Console.WriteLine(" Done");
        }

        /// <summary>
        /// Creates a connection to the RTP stream
        /// </summary>
        public void StartClient()
        {
            // Create new UDP client. The IP end point tells us which IP is sending the data
            client = new UdpClient(port);
            endPoint = new IPEndPoint(IPAddress.Any, port);

            listening = true;
            listenerThread = new Thread(ReceiveCallback);
            listenerThread.Start();

            Console.WriteLine(" [RTPClient] Listening for packets on port " + port + "...");
        }

        /// <summary>
        /// Tells the UDP client to stop listening for packets.
        /// </summary>
        public void StopClient()
        {
            // Set the boolean to false to stop the asynchronous packet receiving
            listening = false;
            Console.WriteLine(" [RTPClient] Stopped listening on port " + port);
        }

        /// <summary>
        /// Handles the receiving of UDP packets from the RTP stream
        /// </summary>
        /// <param name="ar">Contains packet data</param>
        private void ReceiveCallback()
        {
            // Begin looking for the next packet
            while (listening)
            {
                // Receive packet
                byte[] packet = client.Receive(ref endPoint);

                // Decode the header of the packet
                int version = GetRTPHeaderValue(packet, 0, 1);
                int padding = GetRTPHeaderValue(packet, 2, 2);
                int extension = GetRTPHeaderValue(packet, 3, 3);
                int csrcCount = GetRTPHeaderValue(packet, 4, 7);
                int marker = GetRTPHeaderValue(packet, 8, 8);
                int payloadType = GetRTPHeaderValue(packet, 9, 15);
                int sequenceNum = GetRTPHeaderValue(packet, 16, 31);
                int timestamp = GetRTPHeaderValue(packet, 32, 63);
                int ssrcId = GetRTPHeaderValue(packet, 64, 95);

                if (writeHeaderToConsole)
                {
                    Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8}",
                        version,
                        padding,
                        extension,
                        csrcCount,
                        marker,
                        payloadType,
                        sequenceNum,
                        timestamp,
                        ssrcId);
                }

                // Write the packet to the audio stream
                audioStream.Write(packet, 12, packet.Length - 12);
            }
        }

        /// <summary>
        /// Grabs a value from the RTP header in Big-Endian format
        /// </summary>
        /// <param name="packet">The RTP packet</param>
        /// <param name="startBit">Start bit of the data value</param>
        /// <param name="endBit">End bit of the data value</param>
        /// <returns>The value</returns>
        private int GetRTPHeaderValue(byte[] packet, int startBit, int endBit)
        {
            int result = 0;

            // Number of bits in value
            int length = endBit - startBit + 1;

            // Values in RTP header are big endian, so need to do these conversions
            for (int i = startBit; i <= endBit; i++)
            {
                int byteIndex = i / 8;
                int bitShift = 7 - (i % 8);
                result += ((packet[byteIndex] >> bitShift) & 1) * (int)Math.Pow(2, length - i + startBit - 1);
            }
            return result;
        }
    }

मुझे लगता है कि आपको इसे सरल बनाना चाहिए। आरटीपी को पकड़ने के लिए आरटीपी और विशेष पुस्तकालय का उपयोग क्यों करें? क्यों न सिर्फ रासप्रिरी पीई से ऑडियो डेटा लेते हैं और एचटीटीपी पोस्ट का इस्तेमाल अपने सर्वर पर भेजने के लिए करते हैं?

ध्यान रखें कि System.Speech एमपी 3 प्रारूप का समर्थन नहीं करता है यह सहायक हो सकता है - SAPI v5.1 के साथ सहायता SpeechRecognitionEngine हमेशा सी # के साथ एक ही गलत परिणाम देता है । सिस्टम के लिए। स्पीच ऑडियो पीसीएम, यूला, या एओएल प्रारूप में होना चाहिए। यह निर्धारित करने का सबसे विश्वसनीय तरीका है कि आपका पहचानकर्ता किस प्रारूप का समर्थन करता है, इसे RecognizerInfo.SupportedAudioFormats के साथ पूछताछ करना है।

तब आप अपने सर्वर पर डेटा पोस्ट कर सकते हैं (और ContentType = "audio / x-wav" का उपयोग करें)। हमने जैसे एक यूआरएल प्रारूप का इस्तेमाल किया है

http://server/app/recognize/{sampleRate}/{bits}/{isStereo}

अनुरोध में ऑडियो पैरामीटर शामिल करने के लिए POST बॉडी में कैप्चर किए गए wav फ़ाइल को भेजें।

हम एक पकड़ में आ गए, हमें डाटा को भेजने से पहले उसे एक वाएव फाइल हेडर जोड़ना पड़ा। स्पीच हमारा डेटा पीसीएम था, लेकिन WAV प्रारूप में नहीं। Https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ देखें अगर आपको यह करने की आवश्यकता है।