
{"id":2126,"date":"2026-10-04T13:30:16","date_gmt":"2026-10-04T11:30:16","guid":{"rendered":"https:\/\/www.pcjv.de\/?p=2126"},"modified":"2026-10-04T13:30:16","modified_gmt":"2026-10-04T11:30:16","slug":"go-pocket-tts","status":"publish","type":"post","link":"https:\/\/www.pcjv.de\/?p=2126","title":{"rendered":"Pocket-sized speech, in Go"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Kyutai&#8217;s <a href=\"https:\/\/github.com\/kyutai-labs\/pocket-tts\" target=\"_blank\" rel=\"noopener\">PocketTTS<\/a> is a text-to-speech model small enough to run on a CPU. Its reference implementation is Python and PyTorch. <a href=\"https:\/\/github.com\/CWBudde\/go-pocket-tts\" target=\"_blank\" rel=\"noopener\">go-pocket-tts<\/a> runs the same model as a single Go binary: it reads the safetensors weights directly and needs neither Python nor ONNX Runtime.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It got one sentence in <a href=\"\/?p=1981\">Audio on Linux, in Go<\/a>. It deserves more than that, because upstream has moved on since then: a September model, German, a 24-layer variant and a new kind of sampler. This weekend I brought the port up to upstream v3.3.0. That came to 25 pull requests and 116 commits in two days, and German is part of it.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Listen first<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Both clips below were made today with the commands shown under them. Each is a single take, cut only by the model&#8217;s own end-of-speech decision. The only processing afterwards was loudness normalisation and MP3 encoding.<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"\/wordpress\/wp-content\/uploads\/go-pocket-tts-en.mp3\"><\/audio><figcaption class=\"wp-element-caption\">English: <code>english_2026-09<\/code> with the default voice <code>alba<\/code>. 8.2 s of audio.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"\/wordpress\/wp-content\/uploads\/go-pocket-tts-de-24l-tts.mp3\"><\/audio><figcaption class=\"wp-element-caption\">German: the 24-layer <code>german_24l<\/code> with the default voice <code>juergen<\/code>, reading upstream&#8217;s own German demo text. 6.1 s of audio.<\/figcaption><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/pockettts synth --language english_2026-09 \\\n  --text \"Hello. I am a text to speech model, running in pure Go on an ordinary laptop CPU. No Python, and no ONNX Runtime.\" \\\n  --out en.wav\n\n.\/pockettts synth --language german_24l \\\n  --text \"Hallo Welt. Ich bin Pocket TTS von Kyutai. Ich bin schnell genug, um auch auf kleinen CPUs zu laufen. Ich hoffe, ich gefalle dir.\" \\\n  --out de.wav<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As a check that does not depend on my ears, I ran both files through Whisper. It returned both texts word for word. The only slips were the proper nouns: &#8220;Onyx runtime&#8221; and &#8220;Qtai&#8221;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Some honest numbers, from a laptop with an AMD Ryzen 5 4600H. The English clip comes from a 6-layer model, and generating it took 10.1 s for 8.2 s of audio, about 0.8\u00d7 real time, with a peak of 1.6 GB of memory. The German clip comes from the 24-layer model, which is about three times the weights: 10.8 s for 6.1 s of audio, about 0.6\u00d7 real time, with a peak of 3.4 GB. So neither is faster than real time on this machine. That is consistent with the model being built to fit a CPU.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Or try it in your browser<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">No need to build anything to hear it: the <a href=\"https:\/\/cwbudde.github.io\/go-pocket-tts\/\" target=\"_blank\" rel=\"noopener\">web demo<\/a> runs the same Go code, compiled to WebAssembly. Pick a model and a voice, type something and press Synthesize. The page bundles no model of its own. It fetches model, tokenizer and voices straight from Hugging Face, at the same pinned revisions the command line uses.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1736\" height=\"1132\" src=\"\/wordpress\/wp-content\/uploads\/go-pocket-tts-web-demo-24l.png\" alt=\"The go-pocket-tts web demo after synthesizing German text with the 24-layer german_24l model and the voice juergen\" class=\"wp-image-2125\" srcset=\"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/go-pocket-tts-web-demo-24l.png 1736w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/go-pocket-tts-web-demo-24l-300x196.png 300w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/go-pocket-tts-web-demo-24l-1024x668.png 1024w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/go-pocket-tts-web-demo-24l-768x501.png 768w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/go-pocket-tts-web-demo-24l-1536x1002.png 1536w\" sizes=\"auto, (max-width: 1736px) 100vw, 1736px\" \/><figcaption class=\"wp-element-caption\">The demo with the 24-layer German model and the voice juergen. The browser is much slower than the native binary: this 6-second clip took 51 s on the same laptop, after a 670 MB download.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Five of the six models work in the browser, <code>german_24l<\/code> included. The sixth, <code>english_2026-09_24l<\/code>, is left out for now. Its checkpoint is 1.3 GB. It loads, but then the Mimi decoder runs out of 32-bit WebAssembly address space with 4.27 GB in use.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is in the box<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The project is about 50,000 lines of Go, and 131 of its 250 source files are tests. It ships two binaries. <code>pockettts<\/code> is the one you use:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>synth<\/code><\/strong> turns text into a 24 kHz WAV file. It reads from a flag or from stdin and can split long text into sentence chunks.<\/li>\n<li><strong><code>serve<\/code><\/strong> is an HTTP server with <code>POST \/tts<\/code>, <code>GET \/voices<\/code> and <code>GET \/health<\/code>. It has a worker pool and shuts down gracefully.<\/li>\n<li><strong><code>model download<\/code><\/strong> and <strong><code>model verify<\/code><\/strong> fetch checkpoints from Hugging Face, pinned to a revision and checked against SHA256 sums.<\/li>\n<li><strong><code>doctor<\/code><\/strong> checks whether everything a language needs is present and consistent before you find out the hard way.<\/li>\n<li><strong><code>export-voice<\/code><\/strong> turns a WAV prompt into a voice file. Today this still goes through the optional ONNX backend.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The default backend, <code>native-safetensors<\/code>, is the whole inference stack written in Go. It has the transformer backbone that generates latent audio frames, the flow head that samples them, and the Mimi decoder that turns them into a waveform, with AVX2\/FMA kernels for the hot loops. An ONNX Runtime backend also exists as a fallback, and the WebAssembly build is what powers the browser demo above.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The resync<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The port was last synced with upstream pocket-tts 2.1.0 in May. Since then, upstream had added 98 commits and reached 3.3.0. Most of that is not code you can copy. It is behaviour you have to match: a different GELU, a new end-of-speech rule, a new tokenizer format, new text handling. Every one of those changes can make the output sound slightly wrong without causing a single error.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the work ran in numbered phases, one pull request per slice. After every slice the full test suite had to pass, and the reference fixtures were regenerated after any change to the numerics.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Model configs as data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The old port was wired to a single checkpoint, <code>tts_b6369a24<\/code>, with its quirks hard-coded in Go. Upstream now describes every model in a YAML config: layer count, sampler type, text-preparation rules, tokenizer, default temperature, how many frames to generate after end-of-speech. The first phase ported that config layer and embedded upstream&#8217;s configs in the binary. A model is now selected with a flag:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th><code>--language<\/code><\/th><th>Layers<\/th><th>Sampler<\/th><th>Default voice<\/th><\/tr><\/thead><tbody>\n<tr><td><code>english_2026-01<\/code><\/td><td>6<\/td><td>LSD<\/td><td>alba<\/td><\/tr>\n<tr><td><code>english_2026-09<\/code><\/td><td>6<\/td><td>LSD<\/td><td>alba<\/td><\/tr>\n<tr><td><code>english_2026-09_24l<\/code><\/td><td>24<\/td><td>LSD<\/td><td>alba<\/td><\/tr>\n<tr><td><code>english_drifting_26-09<\/code><\/td><td>6<\/td><td>drifting<\/td><td>alba<\/td><\/tr>\n<tr><td><code>german<\/code><\/td><td>6<\/td><td>LSD<\/td><td>juergen<\/td><\/tr>\n<tr><td><code>german_24l<\/code><\/td><td>24<\/td><td>LSD<\/td><td>juergen<\/td><\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Each language comes with 27 predefined voices. The 6-layer models hold about 210\u2013235 MB of weights, and <code>german_24l<\/code> about 670 MB. Every file is pinned to a Hugging Face revision and a checksum, so &#8220;it worked on my machine&#8221; means the same bytes on yours.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Numerics<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Some of these changes were small to write and large in effect. Upstream switched its transformer layers from the exact, erf-based GELU to the tanh approximation, so the Go port did too, at all three places it is used. The difference is small per value, but the model runs autoregressively, and small differences compound over hundreds of steps. Newer models expect a BOS token in front of the voice prompt. The stopping rule for generation was changed to match upstream&#8217;s exactly. Every chunk now fades in after decoding, using torch-style <code>linspace<\/code> ramps, because &#8220;the same fade&#8221; has to mean the same samples.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The flow head was generalised as well. The September models come in two kinds: LSD, which samples with two time conditions, and the new <em>drifting<\/em> head, which has none and produces a frame in a single step. The Go code now reads from the checkpoint how many time embeddings it has and dispatches on that. A small observation from the first smoke run: the same 11-word sentence took 40 frames with the drifting model and 50 with the January LSD model.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Text and tokens<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before a model sees any text, the text is cleaned, capitalised, split into chunks and tokenised, and each of those steps can go wrong in its own way. I ported upstream&#8217;s token-based sentence splitter, and a new loader reads Hugging Face <code>tokenizer.json<\/code> files (Unigram with byte fallback), which is what the new models ship with.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Both are tested against goldens generated by the Python originals, including the cases where Python and Go disagree about Unicode without saying so. Python&#8217;s <code>str.isdigit()<\/code> accepts <code>\u00b2<\/code> and <code>&#9312;<\/code>, but Go&#8217;s <code>unicode.IsDigit<\/code> does not. Normalising <code>\u2026<\/code> into <code>...<\/code> turns one character into three sentence ends. German brings <code>3,50 \u20ac<\/code>, <code>24.12.<\/code> and \u201ethese quotes\u201c. The splitter now passes all 29 golden cases. Four of them failed with the old encoder.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Several languages, one server<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Upstream&#8217;s server runs one language per process. Mine can now serve several from one process. A request picks its model with a <code>language<\/code> field, and the models live in a small LRU registry:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/pockettts serve --language german --server-languages english_2026-01\ncurl -s -X POST http:\/\/localhost:8080\/tts \\\n  -d '{\"text\":\"Hello there.\",\"language\":\"english_2026-01\"}' -o hello.wav<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Each model loads on its first request. At most <code>--server-max-languages<\/code> stay loaded (two by default). The least recently used model leaves the registry right away but is only freed once its running requests have finished, so memory can briefly go over the cap, and it is honest about that. Review found two problems in the first version, both of which only show up under real traffic:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A model that was still loading could be evicted, so the next request started a second load of the same weights.<\/li>\n<li>A request loaded its model before it had a worker slot, so requests waiting in the queue could still fill the memory.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Both are fixed: loads now run on their own goroutine and can be cancelled, eviction skips models that are still loading, and a request only touches the weights once it is allowed to run.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two other server changes. <code>serve --default-voice<\/code> accepts a voice ID, a local file, or a pinned <code>hf:\/\/\u2026@revision<\/code> reference. And the server now refuses to start if its default voice cannot be loaded, instead of starting and then failing every request that does not name a voice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Trying it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The ungated Hugging Face repository is enough: no account and no token needed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/CWBudde\/go-pocket-tts\ncd go-pocket-tts\ngo build -o pockettts .\/cmd\/pockettts\n.\/pockettts model download --language german \\\n  --hf-repo kyutai\/pocket-tts-without-voice-cloning\n.\/pockettts doctor --language german\n.\/pockettts synth --language german --text \"Guten Tag.\" --out hallo.wav<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The code is at <a href=\"https:\/\/github.com\/CWBudde\/go-pocket-tts\" target=\"_blank\" rel=\"noopener\">github.com\/CWBudde\/go-pocket-tts<\/a>, and the credit for the model goes to Kyutai: all the port does is take Python out of the picture.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Kyutai&#8217;s PocketTTS is a text-to-speech model small enough to run on a CPU. Its reference implementation is Python and PyTorch. go-pocket-tts runs the same model as a single Go binary: it reads the safetensors weights directly and needs neither Python nor ONNX Runtime. It got one sentence in Audio on Linux, in Go. It deserves [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":2165,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,41],"tags":[],"class_list":["post-2126","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dsp","category-go"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Pocket-sized speech, in Go - Christian&#039;s private site<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pcjv.de\/?p=2126\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Pocket-sized speech, in Go\",\"datePublished\":\"2026-10-04T11:30:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126\"},\"wordCount\":1400,\"image\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-go-pocket-tts.jpg\",\"articleSection\":[\"DSP\",\"Go\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126\",\"url\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126\",\"name\":\"Pocket-sized speech, in Go - Christian&#039;s private site\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-go-pocket-tts.jpg\",\"datePublished\":\"2026-10-04T11:30:16+00:00\",\"author\":{\"@id\":\"\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.pcjv.de\\\/?p=2126\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#primaryimage\",\"url\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-go-pocket-tts.jpg\",\"contentUrl\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-go-pocket-tts.jpg\",\"width\":480,\"height\":360},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2126#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.pcjv.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Pocket-sized speech, in Go\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/#website\",\"url\":\"https:\\\/\\\/www.pcjv.de\\\/\",\"name\":\"Christian&#039;s private site\",\"description\":\"Private site of Christian-W. Budde\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.pcjv.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Pocket-sized speech, in Go - Christian&#039;s private site","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pcjv.de\/?p=2126","twitter_misc":{"Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pcjv.de\/?p=2126#article","isPartOf":{"@id":"https:\/\/www.pcjv.de\/?p=2126"},"author":{"name":"","@id":""},"headline":"Pocket-sized speech, in Go","datePublished":"2026-10-04T11:30:16+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pcjv.de\/?p=2126"},"wordCount":1400,"image":{"@id":"https:\/\/www.pcjv.de\/?p=2126#primaryimage"},"thumbnailUrl":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-go-pocket-tts.jpg","articleSection":["DSP","Go"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.pcjv.de\/?p=2126","url":"https:\/\/www.pcjv.de\/?p=2126","name":"Pocket-sized speech, in Go - Christian&#039;s private site","isPartOf":{"@id":"https:\/\/www.pcjv.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.pcjv.de\/?p=2126#primaryimage"},"image":{"@id":"https:\/\/www.pcjv.de\/?p=2126#primaryimage"},"thumbnailUrl":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-go-pocket-tts.jpg","datePublished":"2026-10-04T11:30:16+00:00","author":{"@id":""},"breadcrumb":{"@id":"https:\/\/www.pcjv.de\/?p=2126#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pcjv.de\/?p=2126"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pcjv.de\/?p=2126#primaryimage","url":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-go-pocket-tts.jpg","contentUrl":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-go-pocket-tts.jpg","width":480,"height":360},{"@type":"BreadcrumbList","@id":"https:\/\/www.pcjv.de\/?p=2126#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pcjv.de\/"},{"@type":"ListItem","position":2,"name":"Pocket-sized speech, in Go"}]},{"@type":"WebSite","@id":"https:\/\/www.pcjv.de\/#website","url":"https:\/\/www.pcjv.de\/","name":"Christian&#039;s private site","description":"Private site of Christian-W. Budde","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pcjv.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/posts\/2126","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2126"}],"version-history":[{"count":0,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/posts\/2126\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/media\/2165"}],"wp:attachment":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}