I am trying to send captions to a YouTube Live stream (in real time). None of the documentation I've found seems to be accurate.
This page seems closest: https://support.google.com/youtube/answer/6077032?&ref_topic=2853697
But it's still quite wrong. I'm going to walk through what I've done.
They NEVER appear.
My debug statement is this:
Sending to http://upload.youtube.com/closedcaption?cid=abcd-abcd-abcd-abcd-f77s&lang=en-US&seq=364. Body: -->2021-02-10T18:08:46.609 Do not pass go. <--
That is, I'm doing a a POST to the URL in question, Content-Type is set to text/plain. The body is the date/time in Zulu, a newline, my text, and one more newline.
I'm logging this output:
2021/02/10 18:09:09,411 pid<1633> INFO:Post Caption status code: 200
2021/02/10 18:09:09,411 pid<1633> INFO:Post Caption Returned: "2021-02-10T18:09:09.392\n"
That is, YouTube is returning HTTP_OK (200) with a timestamp and nothing else. In other words, it APPEARS to be accepting the caption.
I've made sure I have Show Captions turned on inside the viewer window.
Captions never appear.
I just added the lang argument in case that was the issue -- it doesn't make a difference. I have no idea what I'm doing wrong.
And I can't find any accurate documentation. The page I linked earlier is WRONG. The URL that the website gives as I'm setting up doesn't look anything like what is documented on that page.
You would think, given that YouTube is owned by Google, that a Google search for documentation would actually return some documentation. I actually found the linked page in a StackOverflow answer.
So, questions...
Does anyone know what I might be doing wrong, or have some hints of things I can try?
Does anyone know where I can find up-to-date documentation?
To reiterate:
A. Live streaming (not uploaded video)
B. Captions do NOT appear in the YouTube player
And help or even hints is appreciated.
Post a caption: This Sending to http://upload.youtube.com/closedcaption?cid=5gb9-x5z8-szbb-ghrr-f77s&seq=50. Body: -->2021-02-20T16:38:16.610 This <-- Post a caption: is Sending to http://upload.youtube.com/closedcaption?cid=5gb9-x5z8-szbb-ghrr-f77s&seq=51. Body: -->2021-02-20T16:38:18.827 is <-- Sending to http://upload.youtube.com/closedcaption?cid=5gb9-x5z8-szbb-ghrr-f77s&seq=52. Body: -->2021-02-20T16:38:20.800
<-- Post a caption: a Sending to http://upload.youtube.com/closedcaption?cid=5gb9-x5z8-szbb-ghrr-f77s&seq=53. Body: -->2021-02-20T16:38:21.047 a <-- Post a caption: test. Sending to http://upload.youtube.com/closedcaption?cid=5gb9-x5z8-szbb-ghrr-f77s&seq=54. Body: -->2021-02-20T16:38:23.264 test. <--
Each message replies with something like this:
2021/02/20 16:37:50,555 pid<538> INFO:Post Caption status code: 200 2021/02/20 16:37:50,555 pid<538> INFO:Post Caption Returned: "2021-02-20T16:37:50.537\n"
I am applying a delta based on the date/time that YouTube sends back, and I am fairly sure that part works.
My results:
-Captions appearing inconsistently. I'm sending with a 2-second delay, and I may or may not see a caption appear.
-When they appear, they stay on the screen very briefly (roughly a 1/2 to 1 second).
-And they appear double:
This is
This is
I'm surprised that. YouTube is generating an http: instead of https:. Switching my URL very slightly changes the behavior, but not enough to matter.
Sending Captions to a YouTube Live Stream
Yes, that is totally possible! Let me elaborate.
In order to send closed captions to a live stream, you need to use the contentDetails.closedCaptionsType
(contentDetails.enableClosedCaptions
is deprecated!) property. You want to send your captions via HTTP POST into the ingestion URL of your live stream - see the documentation:
closedCaptionsHttpPost: You will send captions, via HTTP POST, to an ingestion URL associated with your live stream.
On a slight off-topic note, you can get your ingestion URL via contentDetails.closedCaptionsIngestionUrl
. It should look like http://upload.youtube.com/closedcaption?cid=xxx-xxx-xxx-xxx
, whereas xxx-xxx-xxx-xxx
will vary at your end. For further reading, please check out the documentation.
So.. how do you send closed captions? First off, bear in mind that there are some limitations and requirements. Secondly, decide whether you need to send your CC via a normal HTTP POST request or embedded - see HLS ingestion documentation:
HLS ingestion supports two options for sending closed captions:
- Send closed captions via separate HTTP POST requests. This works for all HLS ingestions.
- Embedded 608/708 closed captions work with HLS ingestions that use the H264 video codec but not with ingestions that use the HEVC video codec. See the Live Caption Requirements in the YouTube Help Center for more details.
What follows is an example of a HTTP POST request to the YouTube API via Python (considering the data that needs to be parsed into, e.g. datetime):
import requests
from datetime import datetime
cc = 'This is a test'
headers = {'content-type': 'text/plain'}
ingestion_url = 'http://upload.youtube.com/closedcaption?id=xxx-xxx-xxx-xxx=' + str(seq)
#Specify your details
server = ' region:reg1#cue1'
#Formatting the time properly
time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3]
post = time + server + '\n' + cc + '\n'
requests.post(url=ingestion_url, data=post.encode('utf-8'), headers=headers)
Please note:
{'content-type': 'text/plain'}
and .encode('utf-8')
str(seq)
is referring to the count string - it must be included in every POST request. Check here.As you didn't specify the programming language, I went ahead and chose Python. Though you can send the POST request via a normal ingestion url as well. As mentioned couple of times before, the "golden page for your project" shows how to use the pre-given ingestion url (which YouTube will deliver to you) and how to modify it according to said documentation.
Also note that my explanation above was for their staging server (for simplicity reasons). If you want to test it in the wild, don't forget you need to include parameters like id
, ns
, sparamas
, expire
, signature
, key
and seq
.