Repository: ggerganov/whisper.cpp
File: examples/server/server.cpp (C++)

Code before:
            // Get language probabilities
            std::vector<float> lang_probs(whisper_lang_max_id() + 1, 0.0f);
            const auto detected_lang_id = whisper_lang_auto_detect(ctx, 0, params.n_threads, lang_probs.data());
            
            json jres = json{
                {"task", params.translate ? "translate" : "transcribe"},
                {"language", whisper_lang_str_full(whisper_full_lang_id(ctx))},
                {"duration", float(pcmf32.size())/WHISPER_SAMPLE_RATE},
                {"text", results},
                {"segments", json::array()}
            };

            // Always include language detection info
            json lang_info = json::object();
            // Include the probability of the detected language
            lang_info["probability"] = lang_probs[detected_lang_id];
            
            // Add all language probabilities
            json all_lang_probs = json::object();
            for (int i = 0; i <= whisper_lang_max_id(); ++i) {
                if (lang_probs[i] > 0.001f) { // Only include non-negligible probabilities
                    all_lang_probs[whisper_lang_str(i)] = lang_probs[i];
                }
            }
            lang_info["language_probabilities"] = all_lang_probs;
            jres["language_detection"] = lang_info;

            const int n_segments = whisper_full_n_segments(ctx);
            for (int i = 0; i < n_segments; ++i)
            {
                json segment = json{
                    {"id", i},
                    {"text", whisper_full_get_segment_text(ctx, i)},
                };

                if (!params.no_timestamps) {
                    segment["start"] = whisper_full_get_segment_t0(ctx, i) * 0.01;
                    segment["end"] = whisper_full_get_segment_t1(ctx, i) * 0.01;
                }

                float total_logprob = 0;
                const int n_tokens = whisper_full_n_tokens(ctx, i);
                for (int j = 0; j < n_tokens; ++j) {
                    whisper_token_data token = whisper_full_get_token_data(ctx, i, j);
                    if (token.id >= whisper_token_eot(ctx)) {
                        continue;
                    }

                    segment["tokens"].push_back(token.id);
                    json word = json{{"word", whisper_full_get_token_text(ctx, i, j)}};
                    if (!params.no_timestamps) {

Review comment (suggestion):
Perhaps this could be add to `jres` directly so that it is easy to see all the attributes returned in one place, for example:
```c++
            json jres = json{                                                   
                {"task", params.translate ? "translate" : "transcribe"},        
                {"language", whisper_lang_str_full(whisper_full_lang_id(ctx))}, 
                {"duration", float(pcmf32.size())/WHISPER_SAMPLE_RATE},         
                {"text", results},                                              
                {"segments", json::array()},                                    
                {"language_detection", lang_info},                              
            };
```

Code after:
            std::vector<float> lang_probs(whisper_lang_max_id() + 1, 0.0f);
            const auto detected_lang_id = whisper_lang_auto_detect(ctx, 0, params.n_threads, lang_probs.data());
            json jres = json{
                {"task", params.translate ? "translate" : "transcribe"},
                {"language", whisper_lang_str_full(whisper_full_lang_id(ctx))},
                {"duration", float(pcmf32.size())/WHISPER_SAMPLE_RATE},
                {"text", results},
                {"segments", json::array()},
                {"detected_language", whisper_lang_str_full(detected_lang_id)},
                {"detected_language_probability", lang_probs[detected_lang_id]},
                {"language_probabilities", json::object()}
            };
            // Add all language probabilities
            for (int i = 0; i <= whisper_lang_max_id(); ++i) {
                if (lang_probs[i] > 0.001f) { // Only include non-negligible probabilities
                    jres["language_probabilities"][whisper_lang_str(i)] = lang_probs[i];
                }
            }
            const int n_segments = whisper_full_n_segments(ctx);
            for (int i = 0; i < n_segments; ++i)
            {
                json segment = json{
                    {"id", i},
                    {"text", whisper_full_get_segment_text(ctx, i)},
                };

                if (!params.no_timestamps) {
                    segment["start"] = whisper_full_get_segment_t0(ctx, i) * 0.01;
                    segment["end"] = whisper_full_get_segment_t1(ctx, i) * 0.01;
                }

                float total_logprob = 0;
                const int n_tokens = whisper_full_n_tokens(ctx, i);
                for (int j = 0; j < n_tokens; ++j) {
                    whisper_token_data token = whisper_full_get_token_data(ctx, i, j);
                    if (token.id >= whisper_token_eot(ctx)) {
                        continue;
                    }

                    segment["tokens"].push_back(token.id);
                    json word = json{{"word", whisper_full_get_token_text(ctx, i, j)}};
                    if (!params.no_timestamps) {
                        word["start"] = token.t0 * 0.01;
                        word["end"] = token.t1 * 0.01;
                        word["t_dtw"] = token.t_dtw;
                    }
                    word["probability"] = token.p;
                    total_logprob += token.plog;
                    segment["words"].push_back(word);
                }