Convert SRT to VTT with Go

Convert subtitle formats in Go with the SubtoVTT API. net/http and multipart, no dependencies. Free API key, 100 credits to start. v1 · stable

Convert SRT to VTT with Go's standard net/http and mime/multipart packages — no third-party dependencies. The whole conversion fits in one function and compiles to a single binary.

Pick Go when you're building a CLI tool, a long-running service, or anything that needs the converted file handed off without a heavyweight runtime.

Convert SRT to VTT

package main

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	const apiURL = "https://api.example.com/api/v1/convert"
	apiKey := os.Getenv("SUBTOVTT_API_KEY")

	var body bytes.Buffer
	writer := multipart.NewWriter(&body)

	file, err := os.Open("movie.srt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	part, err := writer.CreateFormFile("file", "movie.srt")
	if err != nil {
		panic(err)
	}
	if _, err := io.Copy(part, file); err != nil {
		panic(err)
	}
	writer.WriteField("from", "srt")
	writer.WriteField("to", "vtt")
	writer.Close()

	req, err := http.NewRequest(http.MethodPost, apiURL, &body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", writer.FormDataContentType())

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		data, _ := io.ReadAll(resp.Body)
		panic(fmt.Sprintf("conversion failed: %d %s", resp.StatusCode, data))
	}

	fmt.Println("Cues:", resp.Header.Get("X-Cue-Count"))

	out, err := os.Create("movie.vtt")
	if err != nil {
		panic(err)
	}
	defer out.Close()
	io.Copy(out, resp.Body)
}

The multipart.Writer builds the multipart/form-data body for you — the key line is writer.CreateFormFile, which sets the file field. The converted file streams straight from the response into movie.vtt.

Read X-Cue-Count from the response headers to confirm the conversion produced the expected number of cues. Set SUBTOVTT_API_KEY in your environment first (100 free credits on key creation).

Tip: a 400 with a JSON error usually means a field is missing or the source format is unsupported — the error message names the exact field.

Convert between any formats

Next

↑ Back to top