I'm trying to add caption (subtitle) tracks to youtube videos as part of a javascript webapp, but the request always fails with error 400: "The request contains invalid metadata values, which prevent the track from being created. Confirm that the request specifies valid values for the snippet.language, snippet.name, and snippet.videoId properties." However, those values are correct on the face of it, identical to the values downloaded from a get-caption request. I've tried all kinds of variations, name or no name, supplying only the 3 requested values; supplying nearly all values (except status), etc. All the security seems to work OK, the video ID is good, etc... this call just doesn't work. It seems like there's really some other error or unreported issue that it has.
"kind" : "youtube#caption","snippet" : {"videoId" : vid,"language": "en-US", // "en" doesn't work either."name": "", // this is what caption-download had// "name" : "English", // tried this too, didn't wokr"trackKind": "standard","audioTrackType": "unknown","isCC": false,"isLarge": false,"isEasyReader": false,"isDraft": false,"isAutoSynced": false } };// Set up the body boundary = "==BOUND========8325064ayb5719PKSR999ARY="; body = "--" + boundary +"\r\n"; // note two required dashes! body += "Content-Type: application/json\r\n"; body += "MIME-Version: 1.0\r\n"; body += "\r\n"; // end of headers body += JSON.stringify(resource) +"\r\n"; body += "--" + boundary +"\r\n"; // note two required dashes! body += "Content-Type: text/plain; charset=utf-8\r\n"; body += "MIME-Version: 1.0\r\n"; body += "\r\n"; // end of headers body += caps +"\r\n"; body += "--" + boundary +"\r\n"; // note two required dashes!console.log("body: " + body);// Now here we go with the transfer var yourUrl = "https://youtube.googleapis.com/upload/youtube/v3/captions?part=snippet";// +"&sync=false"; // don't try to sync audio to captions! var Httpreq = new XMLHttpRequest(); // a new request Httpreq.open("POST",yourUrl,false); // false = asynchronous Httpreq.setRequestHeader("Authorization", "Bearer " + access_token); Httpreq.setRequestHeader("X-GData-Key", "key=" + ytAPIkey); Httpreq.setRequestHeader("Content-Type", "multipart/mixed; " // or related?+"boundary=\"" + boundary +"\"");// unneeded Httpreq.setRequestHeader("Content-Length", String(len(body)));// NO! "unsafe" : Httpreq.setRequestHeader("Expect", "100-continue"); // ??? Httpreq.send(body); var capbak = Httpreq.responseText; // .status is the code, ie 200 et seq var respco = Httpreq.status;console.log("Status " + Httpreq.status);console.log("Reply: " + capbak);
Comes back with:
Status 400Reply: {"error": {"code": 400,"message": "The request contains invalid metadata values, which prevent the track from being created. Confirm that the request specifies valid values for the \u003ccode\u003esnippet.language\u003c/code\u003e, \u003ccode\u003esnippet.name\u003c/code\u003e, and \u003ccode\u003esnippet.videoId\u003c/code\u003e properties. The \u003ccode\u003esnippet.isDraft\u003c/code\u003e property can also be included, but it is not required.","errors": [ {"message": "The request contains invalid metadata values, which prevent the track from being created. Confirm that the request specifies valid values for the \u003ccode\u003esnippet.language\u003c/code\u003e, \u003ccode\u003esnippet.name\u003c/code\u003e, and \u003ccode\u003esnippet.videoId\u003c/code\u003e properties. The \u003ccode\u003esnippet.isDraft\u003c/code\u003e property can also be included, but it is not required.","domain": "youtube.caption","reason": "invalidMetadata","location": "body.snippet","locationType": "other" } ] }}