/// <summary>
        /// Speech-to-text conversion using HTTP mode.
        /// </summary>
        /// <param name="options">Recognition settings.</param>
        /// <param name="mediaStream">Audio stream used for recognition.</param>
        /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="OperationCanceledException"></exception>
        public async Task <SpeechToTextResult> SpeechToTextAsync(SpeechRecognitionOptions options, Stream mediaStream, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            if (mediaStream == null)
            {
                throw new ArgumentNullException(nameof(mediaStream));
            }

            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();

            var queryParams = new Dictionary <string, string>
            {
                ["uuid"]  = _userId.ToUuid(),
                ["key"]   = _apiKey,
                ["topic"] = options.SpeechModel.GetEnumString(),
                ["lang"]  = options.Language.GetEnumString()
            };

            var queryString = string.Join("&", queryParams.Select(pair => $"{pair.Key}={pair.Value}"));
            var uri         = new Uri($"https://{Configuration.RecognitionEndpointAddress}/asr_xml?{queryString}");

            var message = new HttpRequestMessage(HttpMethod.Post, uri)
            {
                Content = new StreamContent(mediaStream),
            };

            if (message.Content.Headers.ContentLength > 1024 * 1024)
            {
                throw new ArgumentOutOfRangeException(nameof(mediaStream), message.Content.Headers.ContentLength, "Content length must be less then 1 MB.");
            }

            message.Content.Headers.ContentType     = MediaTypeHeaderValue.Parse(options.AudioFormat.GetEnumString());
            message.Headers.TransferEncodingChunked = true;

            try
            {
                var response = await _httpClient.SendAsync(message, cancellationToken).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    return new SpeechToTextResult
                           {
                               TransportStatus = TransportStatus.Ok,
                               StatusCode      = response.StatusCode
                           }
                }
                ;

                using (var contentStream = await response.Content.ReadAsStreamAsync())
                {
                    return(new SpeechToTextResult
                    {
                        TransportStatus = TransportStatus.Ok,
                        StatusCode = response.StatusCode,
                        Result = new UtteranceRecognitionResult(XmlMessageSerializer.DeserializeResponse(contentStream))
                    });
                }
            }
            catch (HttpRequestException)
            {
                return(new SpeechToTextResult {
                    TransportStatus = TransportStatus.SocketError
                });
            }
        }