PageSourceSearch

https://java2ai.com/assets/js/c0843ada.2642f268.js

js java2ai.com collected 2026-10-03 21:33:08 UTC 18,505 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkspring_ai_alibaba_website=self.webpackChunkspring_ai_alibaba_website||[]).push([[1303],{28453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>s});var o=t(96540);const i={},r=o.createContext(i);function l(e){const n=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),o.createElement(r.Provider,{value:n},e.children)}},98032:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>a});const o=JSON.parse('{"id":"multimodals/audio/speech","title":"Text-To-Speech (TTS) API","description":"Spring AI \u901a\u8fc7 TextToSpeechModel \u548c StreamingTextToSpeechModel \u63a5\u53e3\u4e3a Text-To-Speech (TTS) \u63d0\u4f9b\u7edf\u4e00\u7684 API\u3002\u8fd9\u5141\u8bb8\u60a8\u7f16\u5199\u53ef\u5728\u4e0d\u540c TTS \u63d0\u4f9b\u8005\u4e4b\u95f4\u5de5\u4f5c\u7684\u53ef\u79fb\u690d\u4ee3\u7801\u3002","source":"@site/integration/multimodals/audio/speech.md","sourceDirName":"multimodals/audio","slug":"/multimodals/audio/speech","permalink":"/integration/multimodals/audio/speech","draft":false,"unlisted":false,"editUrl":"https://github.com/spring-ai-alibaba/website/tree/main/integration/multimodals/audio/speech.md","tags":[],"version":"current","lastUpdatedBy":"txuw","lastUpdatedAt":1768049689000,"frontMatter":{},"sidebar":"integrationSidebar","previous":{"title":"Multimodality API","permalink":"/integration/multimodals/multimodality"},"next":{"title":"DashScope Text-to-Speech (TTS)","permalink":"/integration/multimodals/audio/speech/dashscope-speech"}}');var i=t(74848),r=t(28453);const l={},s="Text-To-Speech (TTS) API",p={},a=[{value:"Supported Providers",id:"supported-providers",level:2},{value:"Common Interface",id:"common-interface",level:2},{value:"TextToSpeechModel",id:"texttospeechmodel",level:3},{value:"StreamingTextToSpeechModel",id:"streamingtexttospeechmodel",level:3},{value:"TextToSpeechPrompt",id:"texttospeechprompt",level:3},{value:"TextToSpeechResponse",id:"texttospeechresponse",level:3},{value:"Writing Provider-Agnostic Code",id:"writing-provider-agnostic-code",level:2},{value:"Basic Service Example",id:"basic-service-example",level:3},{value:"Advanced Example: Multi-Provider Support",id:"advanced-example-multi-provider-support",level:3},{value:"Streaming Audio Example",id:"streaming-audio-example",level:3},{value:"REST Controller Example",id:"rest-controller-example",level:3},{value:"Configuration-Based Provider Selection",id:"configuration-based-provider-selection",level:3},{value:"Using Portable Options",id:"using-portable-options",level:3},{value:"Working with Provider-Specific Features",id:"working-with-provider-specific-features",level:3},{value:"Best Practices for Portable Code",id:"best-practices-for-portable-code",level:3},{value:"Provider-Specific Features",id:"provider-specific-features",level:2}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"text-to-speech-tts-api",children:"Text-To-Speech (TTS) API"})}),"\n",(0,i.jsxs)(n.p,{children:["Spring AI \u901a\u8fc7 ",(0,i.jsx)(n.code,{children:"TextToSpeechModel"})," \u548c ",(0,i.jsx)(n.code,{children:"StreamingTextToSpeechModel"})," \u63a5\u53e3\u4e3a Text-To-Speech (TTS) \u63d0\u4f9b\u7edf\u4e00\u7684 API\u3002\u8fd9\u5141\u8bb8\u60a8\u7f16\u5199\u53ef\u5728\u4e0d\u540c TTS \u63d0\u4f9b\u8005\u4e4b\u95f4\u5de5\u4f5c\u7684\u53ef\u79fb\u690d\u4ee3\u7801\u3002"]}),"\n",(0,i.jsx)(n.h2,{id:"supported-providers",children:"Supported Providers"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/integration/multimodals/audio/speech/openai-speech",children:"OpenAI's Speech API"})}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/integration/multimodals/audio/speech/dashscope-speech",children:"DashScope Text-To-Speech API"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"common-interface",children:"Common Interface"}),"\n",(0,i.jsx)(n.p,{children:"\u6240\u6709 TTS \u63d0\u4f9b\u8005\u5b9e\u73b0\u4ee5\u4e0b\u5171\u4eab\u63a5\u53e3\uff1a"}),"\n",(0,i.jsx)(n.h3,{id:"texttospeechmodel",children:"TextToSpeechModel"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"TextToSpeechModel"})," \u63a5\u53e3\u63d0\u4f9b\u5c06\u6587\u672c\u8f6c\u6362\u4e3a\u8bed\u97f3\u7684\u65b9\u6cd5\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public interface TextToSpeechModel extends Model<TextToSpeechPrompt, TextToSpeechResponse>, StreamingTextToSpeechModel {\n\n    /**\n     * Converts text to speech with default options.\n     */\n    default byte[] call(String text) {\n        // Default implementation\n    }\n\n    /**\n     * Converts text to speech with custom options.\n     */\n    TextToSpeechResponse call(TextToSpeechPrompt prompt);\n\n    /**\n     * Returns the default options for this model.\n     */\n    default TextToSpeechOptions getDefaultOptions() {\n        // Default implementation\n    }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"streamingtexttospeechmodel",children:"StreamingTextToSpeechModel"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"StreamingTextToSpeechModel"})," \u63a5\u53e3\u63d0\u4f9b\u5b9e\u65f6\u6d41\u5f0f\u4f20\u8f93\u97f3\u9891\u7684\u65b9\u6cd5\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@FunctionalInterface\npublic interface StreamingTextToSpeechModel extends StreamingModel<TextToSpeechPrompt, TextToSpeechResponse> {\n\n    /**\n     * Streams text-to-speech responses with metadata.\n     */\n    Flux<TextToSpeechResponse> stream(TextToSpeechPrompt prompt);\n\n    /**\n     * Streams audio bytes for the given text.\n     */\n    default Flux<byte[]> stream(String text) {\n        // Default implementation\n    }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"texttospeechprompt",children:"TextToSpeechPrompt"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"TextToSpeechPrompt"})," \u7c7b\u5c01\u88c5\u8f93\u5165\u6587\u672c\u548c\u9009\u9879\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'TextToSpeechPrompt prompt = new TextToSpeechPrompt(\n    "Hello, this is a text-to-speech example.",\n    options\n);\n'})}),"\n",(0,i.jsx)(n.h3,{id:"texttospeechresponse",children:"TextToSpeechResponse"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"TextToSpeechResponse"})," \u7c7b\u5305\u542b\u751f\u6210\u7684\u97f3\u9891\u548c\u5143\u6570\u636e\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"TextToSpeechResponse response = model.call(prompt);\nbyte[] audioBytes = response.getResult().getOutput();\nTextToSpeechResponseMetadata metadata = response.getMetadata();\n"})}),"\n",(0,i.jsx)(n.h2,{id:"writing-provider-agnostic-code",children:"Writing Provider-Agnostic Code"}),"\n",(0,i.jsx)(n.p,{children:"\u5171\u4eab TTS \u63a5\u53e3\u7684\u4e3b\u8981\u597d\u5904\u4e4b\u4e00\u662f\u80fd\u591f\u7f16\u5199\u53ef\u5728\u4efb\u4f55 TTS \u63d0\u4f9b\u8005\u4e0a\u5de5\u4f5c\u800c\u65e0\u9700\u4fee\u6539\u7684\u4ee3\u7801\u3002\u5b9e\u9645\u7684\u63d0\u4f9b\u8005\uff08OpenAI\u3001ElevenLabs \u7b49\uff09\u7531\u60a8\u7684 Spring Boot \u914d\u7f6e\u786e\u5b9a\uff0c\u5141\u8bb8\u60a8\u5728\u4e0d\u66f4\u6539\u5e94\u7528\u7a0b\u5e8f\u4ee3\u7801\u7684\u60c5\u51b5\u4e0b\u5207\u6362\u63d0\u4f9b\u8005\u3002"}),"\n",(0,i.jsx)(n.h3,{id:"basic-service-example",children:"Basic Service Example"}),"\n",(0,i.jsx)(n.p,{children:"\u5171\u4eab\u63a5\u53e3\u5141\u8bb8\u60a8\u7f16\u5199\u53ef\u5728\u4efb\u4f55 TTS \u63d0\u4f9b\u8005\u4e0a\u5de5\u4f5c\u7684\u4ee3\u7801\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Service\npublic class NarrationService {\n\n    private final TextToSpeechModel textToSpeechModel;
1\n\n    public NarrationService(TextToSpeechModel textToSpeechModel) {\n        this.textToSpeechModel = textToSpeechModel;\n    }\n\n    public byte[] narrate(String text) {\n        // Works with any TTS provider\n        return textToSpeechModel.call(text);\n    }\n\n    public byte[] narrateWithOptions(String text, TextToSpeechOptions options) {\n        TextToSpeechPrompt prompt = new TextToSpeechPrompt(text, options);\n        TextToSpeechResponse response = textToSpeechModel.call(prompt);\n        return response.getResult().getOutput();\n    }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"\u6b64\u670d\u52a1\u53ef\u4e0e OpenAI\u3001ElevenLabs \u6216\u4efb\u4f55\u5176\u4ed6 TTS \u63d0\u4f9b\u8005\u65e0\u7f1d\u534f\u4f5c\uff0c\u5b9e\u9645\u5b9e\u73b0\u7531\u60a8\u7684 Spring Boot \u914d\u7f6e\u786e\u5b9a\u3002"}),"\n",(0,i.jsx)(n.h3,{id:"advanced-example-multi-provider-support",children:"Advanced Example: Multi-Provider Support"}),"\n",(0,i.jsx)(n.p,{children:"\u60a8\u53ef\u4ee5\u6784\u5efa\u540c\u65f6\u652f\u6301\u591a\u4e2a TTS \u63d0\u4f9b\u8005\u7684\u5e94\u7528\u7a0b\u5e8f\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'@Service\npublic class MultiProviderNarrationService {\n\n    private final Map<String, TextToSpeechModel> providers;\n\n    public MultiProviderNarrationService(List<TextToSpeechModel> models) {\n        // Spring will inject all available TextToSpeechModel beans\n        this.providers = models.stream()\n            .collect(Collectors.toMap(\n                model -> model.getClass().getSimpleName(),\n                model -> model\n            ));\n    }\n\n    public byte[] narrateWithProvider(String text, String providerName) {\n        TextToSpeechModel model = providers.get(providerName);\n        if (model == null) {\n            throw new IllegalArgumentException("Unknown provider: " + providerName);\n        }\n        return model.call(text);\n    }\n\n    public Set<String> getAvailableProviders() {\n        return providers.keySet();\n    }\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"streaming-audio-example",children:"Streaming Audio Example"}),"\n",(0,i.jsx)(n.p,{children:"\u5171\u4eab\u63a5\u53e3\u8fd8\u652f\u6301\u5b9e\u65f6\u97f3\u9891\u751f\u6210\u7684\u6d41\u5f0f\u4f20\u8f93\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Service\npublic class StreamingNarrationService {\n\n    private final TextToSpeechModel textToSpeechModel;\n\n    public StreamingNarrationService(TextToSpeechModel textToSpeechModel) {\n        this.textToSpeechModel = textToSpeechModel;\n    }\n\n    public Flux<byte[]> streamNarration(String text) {\n        // TextToSpeechModel extends StreamingTextToSpeechModel\n        return textToSpeechModel.stream(text);\n    }\n\n    public Flux<TextToSpeechResponse> streamWithMetadata(String text, TextToSpeechOptions options) {\n        TextToSpeechPrompt prompt = new TextToSpeechPrompt(text, options);\n        return textToSpeechModel.stream(prompt);\n    }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"rest-controller-example",children:"REST Controller Example"}),"\n",(0,i.jsx)(n.p,{children:"\u4f7f\u7528\u4e0e\u63d0\u4f9b\u8005\u65e0\u5173\u7684 TTS \u6784\u5efa REST API\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'@RestController\n@RequestMapping("/api/tts")\npublic class TextToSpeechController {\n\n    private final TextToSpeechModel textToSpeechModel;\n\n    public TextToSpeechController(TextToSpeechModel textToSpeechModel) {\n        this.textToSpeechModel = textToSpeechModel;\n    }\n\n    @PostMapping(value = "/synthesize", produces = "audio/mpeg")\n    public ResponseEntity<byte[]> synthesize(@RequestBody SynthesisRequest request) {\n        byte[] audio = textToSpeechModel.call(request.text());\n        return ResponseEntity.ok()\n            .contentType(MediaType.parseMediaType("audio/mpeg"))\n            .header("Content-Disposition", "attachment; filename=\\"speech.mp3\\"")\n            .body(audio);\n    }\n\n    @GetMapping(value = "/stream", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)\n    public Flux<byte[]> streamSynthesis(@RequestParam String text) {\n        return textToSpeechModel.stream(text);\n    }\n\n    record SynthesisRequest(String text) {}\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"configuration-based-provider-selection",children:"Configuration-Based Provider Selection"}),"\n",(0,i.jsx)(n.p,{children:"\u4f7f\u7528 Spring profiles \u6216\u5c5e\u6027\u5728\u63d0\u4f9b\u8005\u4e4b\u95f4\u5207\u6362\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"# application-openai.yml\nspring:\n  ai:\n    model:\n      audio:\n        speech: openai\n    openai:\n      api-key: ${OPENAI_API_KEY}\n      audio:\n        speech:\n          options:\n            model: gpt-4o-mini-tts\n            voice: alloy\n\n# application-elevenlabs.yml\nspring:\n  ai:\n    model:\n      audio:\n        speech: elevenlabs\n    elevenlabs:\n      api-key: ${ELEVENLABS_API_KEY}\n      tts:\n        options:\n          model-id: eleven_turbo_v2_5\n          voice-id: your_voice_id\n"})}),"\n",(0,i.jsx)(n.p,{children:"\u7136\u540e\u6fc0\u6d3b\u6240\u9700\u7684\u63d0\u4f9b\u8005\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# Use OpenAI\njava -jar app.jar --spring.profiles.active=openai\n\n# Use ElevenLabs\njava -jar app.jar --spring.profiles.active=elevenlabs\n"})}),"\n",(0,i.jsx)(n.h3,{id:"using-portable-options",children:"Using Portable Options"}),"\n",(0,i.jsxs)(n.p,{children:["\u4e3a\u4e86\u6700\u5927\u53ef\u79fb\u
1690d\u6027\uff0c\u4ec5\u4f7f\u7528\u901a\u7528 ",(0,i.jsx)(n.code,{children:"TextToSpeechOptions"})," \u63a5\u53e3\u65b9\u6cd5\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@Service\npublic class PortableNarrationService {\n\n    private final TextToSpeechModel textToSpeechModel;\n\n    public PortableNarrationService(TextToSpeechModel textToSpeechModel) {\n        this.textToSpeechModel = textToSpeechModel;\n    }\n\n    public byte[] createPortableNarration(String text) {\n        // Use provider's default options for maximum portability\n        TextToSpeechOptions defaultOptions = textToSpeechModel.getDefaultOptions();\n        TextToSpeechPrompt prompt = new TextToSpeechPrompt(text, defaultOptions);\n        TextToSpeechResponse response = textToSpeechModel.call(prompt);\n        return response.getResult().getOutput();\n    }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"working-with-provider-specific-features",children:"Working with Provider-Specific Features"}),"\n",(0,i.jsx)(n.p,{children:"\u5f53\u60a8\u9700\u8981\u63d0\u4f9b\u8005\u7279\u5b9a\u529f\u80fd\u65f6\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u5728\u4fdd\u6301\u53ef\u79fb\u690d\u4ee3\u7801\u5e93\u7684\u540c\u65f6\u4f7f\u7528\u5b83\u4eec\uff1a"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'@Service\npublic class FlexibleNarrationService {\n\n    private final TextToSpeechModel textToSpeechModel;\n\n    public FlexibleNarrationService(TextToSpeechModel textToSpeechModel) {\n        this.textToSpeechModel = textToSpeechModel;\n    }\n\n    public byte[] narrate(String text, TextToSpeechOptions baseOptions) {\n        TextToSpeechOptions options = baseOptions;\n\n        // Apply provider-specific optimizations if available\n        if (textToSpeechModel instanceof OpenAiAudioSpeechModel) {\n            options = OpenAiAudioSpeechOptions.builder()\n                .from(baseOptions)\n                .model("gpt-4o-tts")  // OpenAI-specific: use high-quality model\n                .speed(1.0)\n                .build();\n        } else if (textToSpeechModel instanceof ElevenLabsTextToSpeechModel) {\n            // ElevenLabs-specific options could go here\n        }\n\n        TextToSpeechPrompt prompt = new TextToSpeechPrompt(text, options);\n        TextToSpeechResponse response = textToSpeechModel.call(prompt);\n        return response.getResult().getOutput();\n    }\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"best-practices-for-portable-code",children:"Best Practices for Portable Code"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"\u4f9d\u8d56\u63a5\u53e3"}),"\uff1a\u59cb\u7ec8\u6ce8\u5165 ",(0,i.jsx)(n.code,{children:"TextToSpeechModel"})," \u800c\u4e0d\u662f\u5177\u4f53\u5b9e\u73b0"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"\u4f7f\u7528\u901a\u7528\u9009\u9879"}),"\uff1a\u575a\u6301\u4f7f\u7528 ",(0,i.jsx)(n.code,{children:"TextToSpeechOptions"})," \u63a5\u53e3\u65b9\u6cd5\u4ee5\u83b7\u5f97\u6700\u5927\u53ef\u79fb\u690d\u6027"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"\u4f18\u96c5\u5904\u7406\u5143\u6570\u636e"}),"\uff1a\u4e0d\u540c\u7684\u63d0\u4f9b\u8005\u8fd4\u56de\u4e0d\u540c\u7684\u5143\u6570\u636e\uff1b\u901a\u7528\u5730\u5904\u7406\u5b83"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"\u4f7f\u7528\u591a\u4e2a\u63d0\u4f9b\u8005\u8fdb\u884c\u6d4b\u8bd5"}),"\uff1a\u786e\u4fdd\u60a8\u7684\u4ee3\u7801\u81f3\u5c11\u4e0e\u4e24\u4e2a TTS \u63d0\u4f9b\u8005\u4e00\u8d77\u5de5\u4f5c"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"\u8bb0\u5f55\u63d0\u4f9b\u8005\u5047\u8bbe"}),"\uff1a\u5982\u679c\u60a8\u4f9d\u8d56\u7279\u5b9a\u7684\u63d0\u4f9b\u8005\u884c\u4e3a\uff0c\u8bf7\u6e05\u695a\u5730\u8bb0\u5f55\u5b83"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"provider-specific-features",children:"Provider-Specific Features"}),"\n",(0,i.jsxs)(n.p,{children:["\u867d\u7136\u5171\u4eab\u63a5\u53e3\u63d0\u4f9b\u4e86\u53ef\u79fb\u690d\u6027\uff0c\u4f46\u6bcf\u4e2a\u63d0\u4f9b\u8005\u8fd8\u901a\u8fc7\u63d0\u4f9b\u8005\u7279\u5b9a\u7684\u9009\u9879\u7c7b\uff08\u4f8b\u5982 ",(0,i.jsx)(n.code,{children:"OpenAiAudioSpeechOptions"}),"\u3001",(0,i.jsx)(n.code,{children:"ElevenLabsSpeechOptions"}),"\uff09\u63d0\u4f9b\u7279\u5b9a\u529f\u80fd\u3002\u8fd9\u4e9b\u7c7b\u5b9e\u73b0 ",(0,i.jsx)(n.code,{children:"TextToSpeechOptions"})," \u63a5\u53e3\uff0c\u540c\u65f6\u6dfb\u52a0\u63d0\u4f9b\u8005\u7279\u5b9a\u7684\u529f\u80fd\u3002"]})]})}function d(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.