{"id":20980446,"url":"https://github.com/flowingspdg/gotv-plus-go","last_synced_at":"2025-05-14T15:30:37.800Z","repository":{"id":44444665,"uuid":"239104419","full_name":"FlowingSPDG/gotv-plus-go","owner":"FlowingSPDG","description":"CS2 CSTV+(aka. GOTV+) tv_broadcast API library written in Go.","archived":false,"fork":false,"pushed_at":"2024-07-10T14:07:18.000Z","size":110,"stargazers_count":38,"open_issues_count":7,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-12T12:08:13.625Z","etag":null,"topics":["counter-strike-global-offensive","cs2","cstv","cstv-plus","gotv","gotv-plus","tv-broadcast"],"latest_commit_sha":null,"homepage":"https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Broadcast","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlowingSPDG.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-08T09:59:04.000Z","updated_at":"2025-04-29T12:59:43.000Z","dependencies_parsed_at":"2024-06-19T00:26:46.555Z","dependency_job_id":null,"html_url":"https://github.com/FlowingSPDG/gotv-plus-go","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowingSPDG%2Fgotv-plus-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowingSPDG%2Fgotv-plus-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowingSPDG%2Fgotv-plus-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowingSPDG%2Fgotv-plus-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlowingSPDG","download_url":"https://codeload.github.com/FlowingSPDG/gotv-plus-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254171537,"owners_count":22026458,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["counter-strike-global-offensive","cs2","cstv","cstv-plus","gotv","gotv-plus","tv-broadcast"],"created_at":"2024-11-19T05:28:34.935Z","updated_at":"2025-05-14T15:30:36.336Z","avatar_url":"https://github.com/FlowingSPDG.png","language":"Go","funding_links":["https://www.buymeacoffee.com/flowingspdg"],"categories":[],"sub_categories":[],"readme":"# GOTV+ Broadcast Server written in Go  \n\n## Author\nShugo Kawamura  \nGithub : [**FlowingSPDG**](http://github.com/FlowingSPDG)  \nTwitter : [**@FlowingSPDG**](http://twitter.com/FlowingSPDG) / [**@FlowingSPDG_EN**](http://twitter.com/FlowingSPDG_EN)  \n\n## Buy me a coffee\n[![\"Buy Me A Coffee\"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/flowingspdg)\n\n## About\nThis is [GOTV+](https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Broadcast) broadcast server interface for Go(Fiber and Gin).  \n  \nGOTV+ is an extension of GOTV where you use HTTP(S) to distribute instead of connecting to a regular GOTV. This makes it easy to serve many more clients around the world with high quality GOTV as you can distribute the content with CDN's.  \nUsing `tv_broadcast` cvars you will enable GOTV+ on your CS:GO Server which will send fragmented data to the GOTV+ ingest (this application) which then serves them to clients which connects to it. The viewer will then watch the feed the same way you would when connecting directly to a GOTV instance.  \n  \nThere are a few projects similar to this. [kunalpowar/csgo-broadacst](https://github.com/kunalpowar/csgo-broadcast)(Go with mux) and [S5Projects/csgo-broadcast](https://github.com/S5Projects/csgo-broadcast)(NodeJS/TypeScript with Express).  \n\n## Usage\n- Launch GOTV+ Server(Fiber example)  \nDirectly using Go: `go run ./examples/inmemory/cmd/main.go -port 8080 -auth gopher`  \nUsing precompiled binary: `./gotv_plus -port :8080 -auth gopher`  \n\n- Enable GOTV broadcast in CS:GO Server by adding this to server.cfg  \n`MATCH_ID` can be what ever you want!  \n```\ntv_enable 1\ntv_broadcast_url \"http://\u003cIP-ADDRESS\u003e:8080/gotv\"\ntv_broadcast_origin_auth \"gopher\"\ntv_broadcast 1\n```\n\n- Connect to GOTV+ from CS:GO Client  \nIn console: `playcast \"http://\u003cIP-ADDRESS\u003e:8080/gotv/MATCH_ID\"`  \n\n### Tips\n- You should configure `tv_broadcast_...` cvars **before** enable broadcast (`tv_broadcast 1`).  \nAnd you may need to restart broadcast if you changed cvars. (`tv_broadcast 0;tv_broadcast 1`).\n- `playcast` and `tv_broadcast_url` URL needs to be wrapped by double quotes (e.g. `playcast \"http://\u003cIP-ADDRESS\u003e:8080/match/MATCH_ID\"`) because of `http:` colon(`:`) is recognized as command seprator for CS:GO.\n- `playcast` and `tv_broadcast_url` does not need slash(`/`) in last character of URL.  \nFor example `playcast \"http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID\"` works properly,  \nwhile `playcast \"http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID/\"` **WILL NOT** work properly.  \nBecause requested URL will be ending with `//sync` (Double-slash).\n\n## Hidden Options\nThere are several hidden options that are not documented. I haven't covered all of the options, but some of them are supported.   \n- \"F\" (e.g. `playcast \"http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID\" f500`) will play match from `500` fragment. CS:GO client will send request to `http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID/sync?fragment=500`\n- \"A\" (e.g. `playcast \"http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID\" a`) will play match from `1` fragment. CS:GO client will send request to `http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID/sync?fragment=1`\n- \"C\" (e.g. `playcast \"http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID\" c`) will play match from `1` fragment. CS:GO client **WILL NOT** send request to `http://\u003cIP-ADDRESS\u003e:8080/match/id/MATCH_ID/sync`, CS:GO client will get 1st fragment directly.\n- \"B\" Option / Skips dem_stop control frame(?)\n\n## Example with Public CDN\nIn this example we run the application with user `gotv`, and then use NGINX to proxy TCP/80 (HTTP) and TCP/443 (HTTPS) traffic to the application. \nWe advice that you limit who can send POST requests (CS:GO servers external/internal IP address) directly to the service with local firewall (iptables, nftables etc), this is the reason why we limit in NGINX all requests to only GET. \n\nWe use two page rules on Cloudflare. We bypass Cache for all requests to /sync as we want that to be served directly from the application, and then cache everything on rest of the URL's. \n\n```\ngotv.example.com/*/sync\nCache Level: Bypass\n\ngotv.example.com/*\nCache Level: Cache Everything\n```\n\nnginx config\n```\nupstream ingest {\n        server \u003cIP-ADDRESS\u003e:8080; # Address to the gotv-plus-go application.\n}\n\nserver {\n\tlisten 80 default_server;\n\tlisten [::]:80 default_server;\n\n\tserver_name _;\n\n\t# Never cache /sync (required for Google CDN and others where you cant configure excluded URL's)\n\tlocation ~* \\/sync$ {\n\t\tadd_header Cache-Control \"no-store\";\n\t\tproxy_pass http://ingest;\n\t}\n\n\t# Only allow GET requests\n\tlocation / {\n\t\tlimit_except GET {\n\t\t\tdeny all;\n\t\t}\n\t\tproxy_pass http://ingest;\n\t}\n\n}\n\nserver {\n\tlisten 443 ssl;\n\tlisten [::]:443 ssl;\n\n\tssl_certificate /etc/ssl/cloudflare/cloudflare-cert.pem;\n\tssl_certificate_key /etc/ssl/cloudflare/cloudflare-key.key;\n\n\tserver_name gotv.example.com;\n\n\t# Never cache /sync (required for Google CDN and others where you cant configure excluded URL's)\n\tlocation ~* \\/sync$ {\n\t\tadd_header Cache-Control \"no-store\";\n\t\tproxy_pass http://ingest;\n\t}\n\n\t# Only allow GET requests\n\tlocation / {\n\t\tlimit_except GET {\n\t\t\tdeny all;\n\t\t}\n\t\tproxy_pass http://ingest;\n\t}\n}\n```\n\nsimple systemd service\n```\n[Unit]\nDescription=GOTV+ service\nAfter=network.target\nStartLimitIntervalSec=0\n\n[Service]\nType=simple\nRestart=always\nRestartSec=1\nUser=gotv\nWorkingDirectory=/path/to/gotv # Required as the application needs template\nExecStart=/path/to/gotv_plus -addr \u003cIP-ADDRESS\u003e:8080 -auth gopher\n\n[Install]\nWantedBy=multi-user.target\n```\n\n## Features\n- Multi matches Support\n- RtDelay/RcVage Support\n- Hidden args support (F/A). F=fragment specification w/o sync request,  A = Play from [1]frag with sync request\n\n## TODO\n- Hidden args support (C/B). C=play from first? B=?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflowingspdg%2Fgotv-plus-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflowingspdg%2Fgotv-plus-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflowingspdg%2Fgotv-plus-go/lists"}