-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflow.json
1 lines (1 loc) · 92 KB
/
flow.json
1
[{"id":"dbbf8510.63c748","type":"tab","label":"IVS Translation V0.2 ","disabled":false,"info":""},{"id":"c726631a.94d11","type":"function","z":"dbbf8510.63c748","name":"set login","func":"\n\nmsg.credentials = {\n client_id: flow.get(\"client_id\"),\n client_secret: flow.get(\"client_secret\")\n};\nmsg.headers = {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n \"Accepts\": \"application/json\"\n};\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":875,"wires":[["1b37b291.50babd"]]},{"id":"94240111.e7aec","type":"inject","z":"dbbf8510.63c748","name":"Inject on load","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":"","x":201.00000762939453,"y":840,"wires":[["401426cb.9c7c98"]]},{"id":"1b37b291.50babd","type":"template","z":"dbbf8510.63c748","name":"Auth Form Encode","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"client_id={{credentials.client_id}}&client_secret={{credentials.client_secret}}&grant_type=client_credentials","x":530,"y":875,"wires":[["495d518d.53edb"]]},{"id":"495d518d.53edb","type":"http request","z":"dbbf8510.63c748","name":"OAuth Server","method":"POST","ret":"obj","paytoqs":false,"url":"https://video.ibm.com/oauth2/token","tls":"","persist":false,"proxy":"","authType":"","x":730,"y":875,"wires":[["10eb2c51.febc34"]]},{"id":"7131b247.45bf3c","type":"debug","z":"dbbf8510.63c748","name":"SM log in","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1235,"y":875,"wires":[]},{"id":"10eb2c51.febc34","type":"function","z":"dbbf8510.63c748","name":"flow.set access and refresh token","func":"flow.set(\"access_token\", msg.payload.access_token); //SM access token. Set upon login\nflow.set(\"refresh_token\", msg.payload.refresh_token); //SM refresh token. Set upon login\n\nreturn msg;","outputs":1,"noerr":0,"x":980,"y":875,"wires":[["7131b247.45bf3c"]]},{"id":"e70e9f0d.c1554","type":"debug","z":"dbbf8510.63c748","name":"flow vars","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":524,"y":840,"wires":[]},{"id":"c7a44dc5.fd67d","type":"inject","z":"dbbf8510.63c748","name":"Inject on load","topic":"","payload":"","payloadType":"date","repeat":"28800","crontab":"","once":true,"onceDelay":"","x":200,"y":875,"wires":[["c726631a.94d11"]]},{"id":"ffb7fa67.144178","type":"link out","z":"dbbf8510.63c748","name":"Job Update","links":["3dffcf82.b9c06"],"x":510,"y":435,"wires":[]},{"id":"9f574b4e.ea6a68","type":"http request","z":"dbbf8510.63c748","name":"Get all videos in channel","method":"GET","ret":"obj","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":275,"y":100,"wires":[["25261edb.598f52","3ab6c26f.bec8fe"]]},{"id":"9a196bf6.59bba8","type":"inject","z":"dbbf8510.63c748","name":"Polling interval ","topic":"","payload":"manual_start","payloadType":"str","repeat":"30","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":40,"wires":[["d2000bae.ca5318"]]},{"id":"d2000bae.ca5318","type":"function","z":"dbbf8510.63c748","name":"set channel flow.get","func":"var apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar channel_id = flow.get(\"SM_channel_id\");\n\n// add channel config in flow var\nvar url = apihost + \"/channels/\" + channel_id + \"/videos.json?filter[protect]=private,public\";\n//https://{{channel_apihost}}/channels/{{CHANNEL_ID}}/videos.json?filter[protect]=private,public\n\n\nvar PutHeader = {\n \"content-type\":\"application/json\",\n \"Authorization\":\"Bearer \" + access_token,\n\n \"Accepts\": \"application/json\"\n\n };\nmsg.mode=\"GET\";\nmsg.url = url;\nmsg.headers = PutHeader;\n\nreturn msg;","outputs":1,"noerr":0,"x":265,"y":70,"wires":[["9f574b4e.ea6a68","ea59f862.66bfb8"]]},{"id":"25261edb.598f52","type":"function","z":"dbbf8510.63c748","name":"get videos","func":"\nmsg.payload= msg.payload.videos\n\nreturn msg;","outputs":1,"noerr":0,"x":235,"y":135,"wires":[["28ec65c0.6b2a3a"]]},{"id":"28ec65c0.6b2a3a","type":"split","z":"dbbf8510.63c748","name":"","splt":"[118,105,100,101,111,115,91,93]","spltType":"bin","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":220,"y":170,"wires":[["4585feb0.791ab","c01a6f56.07bce"]]},{"id":"3ab6c26f.bec8fe","type":"debug","z":"dbbf8510.63c748","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":635,"y":120,"wires":[]},{"id":"4585feb0.791ab","type":"debug","z":"dbbf8510.63c748","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":636,"y":214,"wires":[]},{"id":"d964414c.d51fc","type":"http request","z":"dbbf8510.63c748","name":"get custom metada for field","method":"GET","ret":"obj","url":"","tls":"","x":285,"y":280,"wires":[["54c50c3a.a24944","1e98500f.2825d"]]},{"id":"c0df42b8.bc86f","type":"function","z":"dbbf8510.63c748","name":"set msg.video_object","func":"msg.video_id=msg.payload.id;\nvar video_id=msg.payload.id;\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/custom-metadata.json\n\nvar url = apihost + \"/videos/\" + video_id + \"/custom-metadata.json\";\n//var URL0 = global.get(\"channel_apihost\") + \"/videos/\" + \"122243068\" + \"/custom-metadata.json\";\n\nvar PutHeader = {\n \"content-type\":\"application/json\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\nmsg.url = url;\nmsg.headers = PutHeader;\n\nreturn msg;","outputs":1,"noerr":0,"x":265,"y":245,"wires":[["d964414c.d51fc"]]},{"id":"1e98500f.2825d","type":"function","z":"dbbf8510.63c748","name":"which Caption source field flow.get","func":"\nvar metadata = [];\nmetadata= msg.payload.metadata;\nvar actionField= flow.get(\"actionField\"); // this must be field type list\nvar translate_field= flow.get(\"translate_field\"); // this must be field type list\nvar caption_id_field = flow.get(\"caption_id_field\");\n//msg.video_download_url = msg.video_object.video_download_url; //need download url\n\n\n// ONLY SETS VALUE: caption_id from SM for downstream functions: re-process WC captions, update validated captions\nfor (n=0; n<metadata.length; n++) {\n if (metadata[n].field_id == caption_id_field ){// \"7952\"){\n msg.caption_id = metadata[n].value; // value array means this must be field type list \n \n }\n}\n\n\n\n//captions.json\n\n///*\n// needs to process full job\nfor (i=0; i<metadata.length; i++) {\n if (metadata[i].field_id == translate_field){\n // are there any listed? This is an array.\n //\n // will need another call to see if there is an exisitng caption \n // If true Then if there is a default language selected set source else set source lanugage to default from vars. \n if (metadata[i].value.length >0) {\n msg.action=\"Translate\";\n return [msg,null]; \n }\n \n \n \n }\n}\n\n\nreturn [null,msg];\n\n","outputs":2,"noerr":0,"x":305,"y":315,"wires":[["6fe3a614.ad0f98","8446bd9b.6571c"],["8fb4151c.201a08"]],"outputLabels":["Translate","None"]},{"id":"56a6ff12.6c5e","type":"debug","z":"dbbf8510.63c748","name":"Captions list","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":655,"y":400,"wires":[]},{"id":"54c50c3a.a24944","type":"debug","z":"dbbf8510.63c748","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":640,"y":325,"wires":[]},{"id":"8fb4151c.201a08","type":"debug","z":"dbbf8510.63c748","name":"No","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":645,"y":370,"wires":[]},{"id":"ea59f862.66bfb8","type":"debug","z":"dbbf8510.63c748","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":635,"y":80,"wires":[]},{"id":"6fe3a614.ad0f98","type":"debug","z":"dbbf8510.63c748","name":"Translate","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":790,"y":360,"wires":[]},{"id":"16afb127.14ab6f","type":"comment","z":"dbbf8510.63c748","name":"README","info":"As-is. Conceptual sample. No error handeling. No support or warranty of anytype. Use at own risk.\n#License? Free to use for any purpose. Need to add a license type?\n\nAll on one flow for ease of deployment. Node_RED version 0.20 supports context down into submaps which will be an upgrade once bluemix supports\n\nMust configure variables bottom of flow.\n\n","x":75,"y":85,"wires":[]},{"id":"895e2de0.9aaeb","type":"http in","z":"dbbf8510.63c748","name":"start_job","url":"start_job","method":"get","upload":false,"swaggerDoc":"","x":465,"y":20,"wires":[["31c45e25.d9ebe2","cc820a9f.a0cee8"]]},{"id":"aa1fba6c.32b328","type":"http response","z":"dbbf8510.63c748","name":"","statusCode":"201","headers":{"Content-Type":"text/plain"},"x":845,"y":20,"wires":[]},{"id":"31c45e25.d9ebe2","type":"template","z":"dbbf8510.63c748","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Videos ready for proceessing will start now!\n\nOK to Close window","output":"str","x":705,"y":20,"wires":[["aa1fba6c.32b328"]]},{"id":"e98b38e4.b79758","type":"catch","z":"dbbf8510.63c748","name":"","scope":["daa80ac0.8ce8d8","74cbf572.50fc8c","1117e441.31ba1c","8313a353.54b89","f644fd1c.97735","ad4fd286.c4c6","13541c95.c7d4a3","7454d743.415b98","1b37b291.50babd","ee7b3c4.5aa31c","42f13726.f6c438","739cb53d.0897fc","a551c78a.0f2408","24566836.b71278","39226efe.0f11d2","2c1c5765.764878","e80a47b5.3007f8","f4ff4f69.36d18","b957c083.f1d8d","6023f35d.e96d4c","83a068c5.e856e8","631caa08.35c1c4","50683e3f.46cc9","cca1b9cb.b26b98","837c4d65.b74f4","43f125ef.cf0dfc","70694f40.3b3e2","36a6315.47b74ce","d90830c5.85302","c4263fed.7d7ba","638a2e2e.229cf","44d28e43.0134","43bb2c1a.df4634","8d9df4c0.0087a8","89f610f8.b6bbe","81ff30cc.794db","11190d28.072653","112c9238.f5540e","637d3bd.eb7aec4","10eb2c51.febc34","9f574b4e.ea6a68","cbb52cd7.17009","9ddb3b3d.80be08","d964414c.d51fc","7b9ce3e1.54d72c","6ba55030.45304","f83b0064.302b4","facfe20f.9515d","25261edb.598f52","715926d7.1c4dc8","aa1fba6c.32b328","685f5c1.edc98a4","a3da0304.dcacb","c9355dc2.7b1a6","ecb26338.4ac59","76949f46.1c01c","50337d75.7a72a4","6e83f1c0.3a42c","2d0291ea.1bf29e","94240111.e7aec","c7a44dc5.fd67d","88de6154.908a4","16f82f71.60b311","ee4fd779.cf8a18","322d9ca3.cd1b64","bbd84faf.722fc","ffb7fa67.144178","6fe3a614.ad0f98","e09bbbd7.54cc48","95a6b75c.edd868","8dfd78b1.aa6e78","b17a1eed.ef23d","181d9080.1fe49","c645dd8a.36975","81d509be.3aefd8","b2ac119e.a3937","8367b31f.66ae3","736f49b1.d706d8","c138d0f1.5720e","a898eb40.27baf8","cc83e3e9.259eb","b9cae4dd.f79868","e70e9f0d.c1554","ec44ef6d.9cd86","c51ec010.c8ae4","3ab6c26f.bec8fe","4585feb0.791ab","54c50c3a.a24944","ea59f862.66bfb8","4e509872.32ba68","20a9e4ce.70197c","c425d9a5.2712a8","57c603ea.d2c34c","c40d3c15.8e592","e2f859a2.468238","f58728a3.5bb8e8","ac587db2.b2733","1cb7f004.0e83d","7b9c2397.6c507c","950a6145.7e03f","4787642c.3e5b0c","56a6ff12.6c5e","cd036793.f085a8","3d4b00a0.5eca4","56edefd2.469ac","cec3e3de.fe3d9","495d518d.53edb","6ce0d8ba.56df58","339c288c.518248","e1074b1.ee803b8","70e807c6.dabe58","9a196bf6.59bba8","1fc3eb47.e35245","cc30bb1b.3c5cc8","1002f511.69976b","d2ccf211.45dec","62831480.7cbeac","8fb4151c.201a08","3e5422f5.cf2c7e","56258570.5dcc0c","c78d63bf.ad905","16afb127.14ab6f","276fe374.12747c","167f56e3.eaffb9","caa30c0.f55abf","1c102142.b071bf","8b08787.d213a88","b1269ebb.ab1bb","151be231.223cce","55f0bd8.d287444","d2000bae.ca5318","2f4e063e.5dbd0a","6be64be0.7b4c74","a0013f30.25368","b58a4de0.b3c29","c726631a.94d11","8dc7b679.749de8","c0df42b8.bc86f","bcbbb4b2.37b5d8","28f5fef2.261452","2f7790ee.cf69e","e00ce121.f363d","3a70fe7.b418602","70728556.faa84c","372a5986.cdba66","211caf6a.7e855","e16ff8e1.b1dbf8","4bb073d4.e87d0c","46ce97b.3f96e68","d5e04dba.ffb1c","c8f652c.0de7fb","7131b247.45bf3c","1e263b30.3983d5","1b91dd21.a8ee43","28ec65c0.6b2a3a","b1bb037e.5fcd6","cc97d573.2e0ff8","420d573d.be9348","fb09a249.3772e","895e2de0.9aaeb","efd0751b.7c3ab8","31c45e25.d9ebe2","3d1f1d4c.ced942","19be146e.00cfdc","15822cb9.c5bf53","2f04a98b.0c37b6","b6f8d4f9.b940b8","ba1ec7a2.82ed28","8f925b28.758768","236b33ff.4d1c2c","6be1cb5d.1e0204","11283a18.705cd6","e6fd0f4a.2995","3dffcf82.b9c06","5282086c.014ed8","9791a47c.d55e18","79549fb5.aea73","7fb35ba6.61dba4","4cbdbb2c.b37d14","73e14f45.fe9ac","7b63b4da.9279dc","e5e6dd6c.ae0a","5b92b75c.4f8fd8","503832bd.bf380c","a5c6dc91.73cc1","9c08b62a.358d18","dfa82f9d.3782","823430ea.208d8","e9268a37.71b968","f3838c74.ff41e","710855b1.59b3bc","6a261fe4.1fbab","a7cf6170.c27c9","fef6c526.483208","ca1a06fa.e305a8","e1fe7193.f4bc1","41671888.7d7988","753b7e2c.2c5aa","65bb4b51.5770f4","e4bbb39b.de554","68dadb85.963d14","9058ff29.35a32","d98735e1.36b688","8cfd5266.7e258","1cbcdcad.b603a3","e58922b5.f5ace","4c62420f.e42bdc","23869a94.00bba6","f494b0b3.74794","643a1c3e.aa0934","a351c66.ad15038","62ac9f0a.cb628","51e0047e.7cadcc","c7e4b54e.907478","69650fcd.fd063","1e98500f.2825d","f008a826.49ce98","a9741374.249dd","edc0214b.99b5f","6915c8df.f071e8","3e4b6b71.fa9ee4","f3efdd96.16fb1","7e7660f0.4a5d5","a2e3a2a2.689e7"],"x":150,"y":975,"wires":[["637d3bd.eb7aec4"]]},{"id":"637d3bd.eb7aec4","type":"debug","z":"dbbf8510.63c748","name":"flow errors","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":600,"y":975,"wires":[]},{"id":"70694f40.3b3e2","type":"function","z":"dbbf8510.63c748","name":"create xlate msgs","func":"// get translate_field \nmsg.translate_field=flow.get(\"translate_field\"); //flow.set(\"translate_field\",\"8174\"); IVS field multi select\n// get translate_field values\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id; // make sure passed on at msg level\nvar caption_id=msg.caption_id; // make sure passed on at msg level\nvar WEBVTT=msg.WEBVTT;\nmsg.payload={};\nmsg.caption_id=caption_id;\nmsg.video_id =video_id;\nmsg.WEBVTT=WEBVTT;\n//WEBVTT make sure passed on at msg level\n/* test video_id = \"123509218\";\ncaption_id=\"somecaption\";\nmsg.video_id= video_id;\nmsg.caption_id=caption_id;\n*/\n\n//GET https://{{channel_apihost}}/videos/{{VIDEO_ID}}/custom-metadata.json \nvar url = apihost + \"/videos/\" + video_id + \"/custom-metadata.json\"; // \n\nvar PutHeader = {\n \"content-type\":\"application/json;charset=UTF-8\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\nmsg.url = url;\nmsg.headers = PutHeader;\nmsg.method= \"GET\";\n\n// get translate value - itterate\n// set values for translate and IVS field values. \n\n\nreturn msg;","outputs":1,"noerr":0,"x":1460,"y":420,"wires":[["a67bbb32.a31998"]]},{"id":"339c288c.518248","type":"debug","z":"dbbf8510.63c748","name":"org msg","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1695,"y":460,"wires":[]},{"id":"e6fd0f4a.2995","type":"function","z":"dbbf8510.63c748","name":"translate messages","func":"\n// set values for translate and IVS field values. \n// might want to programmaticaly create translate_model_id. Support multiple source languages. eg. en-es, fr-es, de-es. \n// might also want to take source language and create a captions publish.\n//var parts = msg.parts;\nmsg.parts={}; //20191001\n\nvar metadata = msg.payload.metadata;\nvar translate_to_languages; \nvar translate_field=flow.get(\"translate_field\");\nvar video_id = msg.video_id; // make sure passed on at msg level\nvar caption_id=msg.caption_id; // make sure passed on at msg level\nvar WEBVTT= msg.WEBVTT; // make sure passed on at msg level\nvar translateMsgs = []; // used to send unknown number of translate to messages. eg Spanish, French,....\nvar translate_model_id;\nvar source_language_code = msg.language_source.substring(0,2).toLowerCase();\n\n// https://cloud.ibm.com/docs/services/language-translator?topic=language-translator-identifiable-languages\n// https://{{channel_apihost}}/caption-languages.json\n//msg.payload={};\n//translate_to_languages.forEach(get_language_settings);\n// get translate values - new message for each translate value found\nvar tmpLang;\nvar tmpvalue;\nfor (i=0; i<metadata.length; i++) {\n if (metadata[i].field_id == translate_field){\n tmpLang=\"\";\n tmpvalue=metadata[i].value.length;\n for (il=0; il<tmpvalue; il++) {\n tmpLang=metadata[i].value[il].name; \n// value array means this must be field type list \n // msg.actionValue=metadata[i].value; // could be abstracted more by id of the object which \"2002\" = 'Complete' on source demo system\n switch(tmpLang) {\n case \"Arabic\":\n translate_model_id=source_language_code + \"-ar\";\n language_target=\"ar-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Bulgarian\":\n translate_model_id=source_language_code + \"-bg\";\n language_target=\"bg-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Croatian\":\n translate_model_id=source_language_code + \"-hr\";\n language_target=\"hr-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Czech\":\n translate_model_id=source_language_code + \"-cs\";\n language_target=\"cs-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Danish\":\n translate_model_id=source_language_code + \"-da\";\n language_target=\"da-00\";\n translateMsgs.push({translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Dutch\":\n translate_model_id=source_language_code + \"-nl\";\n language_target=\"nl-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Estonian\":\n translate_model_id=source_language_code + \"-et\";\n language_target=\"et-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Finnish\":\n translate_model_id=source_language_code + \"-fi\";\n language_target=\"fi-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"French\":\n translate_model_id=source_language_code + \"-fr\";\n language_target=\"fr-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"German\":\n translate_model_id=source_language_code + \"-de\";\n language_target=\"de-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n\n case \"Greek\":\n translate_model_id=source_language_code + \"-el\";\n language_target=\"el-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Hebrew\":\n translate_model_id=source_language_code + \"-he\";\n language_target=\"he-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Hindi\":\n translate_model_id=source_language_code + \"-hi\";\n language_target=\"hi-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Italian\":\n translate_model_id=source_language_code + \"-it\";\n language_target=\"it-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Japanese\":\n translate_model_id=source_language_code + \"-ja\";\n language_target=\"ja-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Korean\":\n translate_model_id=source_language_code + \"-ko\";\n language_target=\"ko-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Norwegian Bokmal\": //Norwegian Bokmal\n translate_model_id=source_language_code + \"-nb\";\n language_target=\"nb-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Polish\":\n translate_model_id=source_language_code + \"-pl\";\n language_target=\"pl-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Portuguese\":\n translate_model_id=source_language_code + \"-pt\";\n language_target=\"pt-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Romanian\":\n translate_model_id=source_language_code + \"-ro\";\n language_target=\"ro-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n\n case \"Russian\":\n translate_model_id=source_language_code + \"-ru\";\n language_target=\"ru-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Simplified Chinese\":\n translate_model_id=source_language_code + \"-zh\";\n language_target=\"zh-04\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Slovak\": \n translate_model_id=source_language_code + \"-sk\";\n language_target=\"sk-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Slovenian\": \n translate_model_id=source_language_code + \"-sl\";\n language_target=\"sl-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Spanish\": \n translate_model_id=source_language_code + \"-es\";\n language_target=\"es-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"Swedish\":\n translate_model_id=source_language_code + \"-sv\";\n language_target=\"sv-00\";\n translateMsgs.push({translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Traditional Chinese\":\n translate_model_id=source_language_code + \"-zh-TW\";\n language_target=\"zh-05\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT });\n break;\n \n case \"Turkish\":\n translate_model_id=source_language_code + \"-tr\";\n language_target=\"tr-00\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break;\n \n case \"English\":\n translate_model_id=source_language_code + \"-en\";\n language_target=\"en-US\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break; \n\n case \"English-GB\":\n translate_model_id=source_language_code + \"-en\";\n language_target=\"en-GB\";\n translateMsgs.push({payload:msg,translate_model_id:translate_model_id,language_target:language_target,caption_id:caption_id,video_id:video_id,WEBVTT:WEBVTT});\n break; \n }\n }\n \n }\n}\nif (translateMsgs.length === 0){\n // msg={};\n msg.video_id = video_id;\n msg.caption_id=caption_id;\n return [null,null,msg]; // no languages\n}\n//return [translateMsgs,null,null];\nreturn [translateMsgs,msg,null]; // return original msg on line output 2 if desired.\n","outputs":3,"noerr":0,"x":1455,"y":505,"wires":[["8dfd78b1.aa6e78","b654208e.be8e4","6536771d.ac18d8","eb7a38c4.677648"],["339c288c.518248","a7f51934.2a6248"],["cd036793.f085a8"]]},{"id":"8dfd78b1.aa6e78","type":"debug","z":"dbbf8510.63c748","name":"languages","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1700,"y":420,"wires":[]},{"id":"ba1ec7a2.82ed28","type":"inject","z":"dbbf8510.63c748","name":"test","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1220,"y":310,"wires":[["bcbbb4b2.37b5d8"]]},{"id":"a0013f30.25368","type":"function","z":"dbbf8510.63c748","name":"set get IVS WEBVTT","func":"var video_id = msg.video_id;\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar language_source = msg.language_source;\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/captions/en-US/vtt\n//var url = apihost + \"/videos/\" + msg.video_id +\"/captions/en-US/vtt\"; // \nvar url = apihost + \"/videos/\" + msg.video_id +\"/captions/\" + language_source + \"/vtt\"; // \n\nvar headers = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\nmsg.method=\"GET\";\nmsg.url = url;\nmsg.headers = headers;\nmsg.payload={};\nreturn msg;","outputs":1,"noerr":0,"x":1475,"y":270,"wires":[["715926d7.1c4dc8","c40d3c15.8e592"]]},{"id":"715926d7.1c4dc8","type":"http request","z":"dbbf8510.63c748","name":"get iVS WebVTT","method":"use","ret":"txt","url":"","tls":"","x":1450,"y":305,"wires":[["c71bf22a.39d18","5594492.35471b8"]]},{"id":"73e14f45.fe9ac","type":"function","z":"dbbf8510.63c748","name":"Update captions IVS","func":"// payload is set prior to allow disconnecting and using independantly. Also enables wrapping prior function in split / join. \n// don't combine with prior step unless you understand implications.\\\n\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id;\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/captions/en-US/vtt\nvar url = apihost + \"/videos/\" + video_id + \"/captions/\"+msg.language_target+\"/vtt\"; //\n\nvar PutHeader = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\n\nmsg.url = url;\nmsg.headers = PutHeader;\n\nreturn msg;","outputs":1,"noerr":0,"x":260,"y":560,"wires":[["39226efe.0f11d2","c4263fed.7d7ba","b17a1eed.ef23d"]]},{"id":"41671888.7d7988","type":"http request","z":"dbbf8510.63c748","name":"upload caption","method":"PUT","ret":"txt","url":"","tls":"","x":690,"y":565,"wires":[["e80a47b5.3007f8"]]},{"id":"e80a47b5.3007f8","type":"debug","z":"dbbf8510.63c748","name":"captions upload","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":900,"y":565,"wires":[]},{"id":"710855b1.59b3bc","type":"http request","z":"dbbf8510.63c748","name":"Update SM field value","method":"use","ret":"txt","url":"","tls":"","x":1055,"y":755,"wires":[["c8f652c.0de7fb"]]},{"id":"c8f652c.0de7fb","type":"debug","z":"dbbf8510.63c748","name":"SM field update","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1250,"y":755,"wires":[]},{"id":"b2ac119e.a3937","type":"function","z":"dbbf8510.63c748","name":"set make caption visible","func":"//\n\nvar video_id = msg.video_id;\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\n\n//PUT\thttps://api.video.ibm.com/videos/VIDEO_ID/captions/LANGUAGE.FORMAT (format can be json or xml)\n//var url = apihost + \"/videos/\" + video_id + \"/captions/es-00.json\"; // \nvar url = apihost + \"/videos/\" + video_id + \"/captions/\"+ msg.language_target +\".json\"; // \n\n\nvar PutHeader = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n\n \"Accepts\": \"application/json\"\n\n };\nvar body = {\n \"is_visible\": \"true\"\n\n\n}\n\nmsg.url = url;\nmsg.headers = PutHeader;\nmsg.payload = body;\nreturn msg;","outputs":1,"noerr":0,"x":865,"y":615,"wires":[["4e1ffa05.397094"]]},{"id":"56edefd2.469ac","type":"comment","z":"dbbf8510.63c748","name":"note for this input","info":"Link in expects msg.video_id & msg.caption_id\n\nto test individually set param in func next to test","x":1336,"y":224,"wires":[]},{"id":"bcbbb4b2.37b5d8","type":"function","z":"dbbf8510.63c748","name":"set test","func":"var video_id = \"123541153\"; // your SM video ID goes here\nmsg.video_id = video_id;\nreturn msg;","outputs":1,"noerr":0,"x":1215,"y":345,"wires":[["a0013f30.25368"]]},{"id":"50337d75.7a72a4","type":"http request","z":"dbbf8510.63c748","name":"","method":"GET","ret":"obj","url":"","tls":"","x":235,"y":650,"wires":[["83a068c5.e856e8"]]},{"id":"b1269ebb.ab1bb","type":"function","z":"dbbf8510.63c748","name":"set caption status","func":"// \nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id;\n\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/captions.json\nvar url = apihost + \"/videos/\" + video_id + \"/captions.json\"; // \n\n\nvar PutHeader = {\n \"content-type\":\"application/json\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\n\nmsg.url = url;\nmsg.headers = PutHeader;\nreturn msg;","outputs":1,"noerr":0,"x":255,"y":620,"wires":[["50337d75.7a72a4","7b9c2397.6c507c"]]},{"id":"83a068c5.e856e8","type":"function","z":"dbbf8510.63c748","name":"check caption status","func":"\n \nvar caption_status=false;\nvar captions;\nvar loopMax = 100; // 1,000 seconds 16 min to publish caption. \ncaptions = msg.payload.captions;\nvar loopcount=0;\nloopcount=msg.count;\nif (isNaN(loopcount)){\n msg.count=0;\n} \nif (loopcount >loopMax) {\n return [null,null,msg];\n }\n\nmsg.count=msg.count +1;\nfor (i=0; i<captions.length; i++){\n //if (captions[i].language == 'es-00' && captions[i].status == 'active' ){\n if (captions[i].language == msg.language_target && captions[i].status == 'active' ){ \n caption_status = true;\n return [msg,null,null];\n }\n \n}\n \nreturn [null,msg,null];\n","outputs":3,"noerr":0,"x":565,"y":635,"wires":[["b2ac119e.a3937","ac587db2.b2733","e00e3ca8.53428"],["c4263fed.7d7ba","1cb7f004.0e83d"],["f3dd649f.362bf8"]],"outputLabels":["active","processing",""]},{"id":"c4263fed.7d7ba","type":"delay","z":"dbbf8510.63c748","name":"","pauseType":"delay","timeout":"25","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":220,"y":590,"wires":[["b1269ebb.ab1bb"]]},{"id":"39226efe.0f11d2","type":"debug","z":"dbbf8510.63c748","name":"caption translated","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":520,"y":530,"wires":[]},{"id":"3dffcf82.b9c06","type":"link in","z":"dbbf8510.63c748","name":"translate now","links":["ffb7fa67.144178","46512edd.cc11f"],"x":1270,"y":270,"wires":[["a0013f30.25368"]]},{"id":"cd036793.f085a8","type":"debug","z":"dbbf8510.63c748","name":"no languages","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1700,"y":500,"wires":[]},{"id":"3a70fe7.b418602","type":"change","z":"dbbf8510.63c748","name":"set WEBVTT","rules":[{"t":"set","p":"WEBVTT","pt":"msg","to":"payload","tot":"msg"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1445,"y":380,"wires":[["70694f40.3b3e2"]]},{"id":"c40d3c15.8e592","type":"debug","z":"dbbf8510.63c748","name":"set url get ISV caption","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1700,"y":265,"wires":[]},{"id":"b17a1eed.ef23d","type":"delay","z":"dbbf8510.63c748","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":505,"y":565,"wires":[["41671888.7d7988"]]},{"id":"ac587db2.b2733","type":"debug","z":"dbbf8510.63c748","name":"translate complete","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1010,"y":710,"wires":[]},{"id":"1cb7f004.0e83d","type":"debug","z":"dbbf8510.63c748","name":"translate processing","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":925,"y":645,"wires":[]},{"id":"7b9c2397.6c507c","type":"debug","z":"dbbf8510.63c748","name":"caption status loop","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":535,"y":725,"wires":[]},{"id":"5282086c.014ed8","type":"comment","z":"dbbf8510.63c748","name":"Translate Section","info":"","x":2345,"y":295,"wires":[]},{"id":"cca1b9cb.b26b98","type":"comment","z":"dbbf8510.63c748","name":"Config & login section Section","info":"set flow vars sets up variables for this flow\n\nLogin sets access and refresh token.\nOnly access token is used","x":135,"y":790,"wires":[]},{"id":"70e987de.240928","type":"comment","z":"dbbf8510.63c748","name":"Error handling section","info":"None. Just reports","x":115,"y":930,"wires":[]},{"id":"f3dd649f.362bf8","type":"debug","z":"dbbf8510.63c748","name":"failed caption update","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":925,"y":670,"wires":[]},{"id":"cc820a9f.a0cee8","type":"change","z":"dbbf8510.63c748","name":"","rules":[{"t":"delete","p":"req","pt":"msg"},{"t":"delete","p":"res","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":725,"y":50,"wires":[["d2000bae.ca5318"]]},{"id":"a67bbb32.a31998","type":"http request","z":"dbbf8510.63c748","name":"","method":"use","ret":"obj","url":"","tls":"","x":1435,"y":460,"wires":[["e6fd0f4a.2995"]]},{"id":"c01a6f56.07bce","type":"change","z":"dbbf8510.63c748","name":"","rules":[{"t":"delete","p":"parts","pt":"msg"},{"t":"delete","p":"headers","pt":"msg"},{"t":"delete","p":"url","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":245,"y":210,"wires":[["c0df42b8.bc86f"]]},{"id":"4e79d250.e1f08c","type":"function","z":"dbbf8510.63c748","name":"WEBVTT Creator","func":"// MIT license \n//source: https://github.com/osk/node-webvtt/blob/master/lib/parser.js\n\nvar strict=true;\n\n//const segment = require('./segmenter').segment;\n\nfunction hlsSegment (input, segmentLength, startOffset) {\n\n if (typeof startOffset === 'undefined') {\n startOffset = '900000';\n }\n\n //const segments = segment(input, segmentLength);\n const segments = input;\n const result = [];\n \n\nsegments.forEach((seg, i) => {\n\n// took this out for our purposes. X-TIMESTAMP-MAP=MPEGTS:${startOffset},LOCAL:00:00:00.000\n// fails parsing using // source: https://github.com/osk/node-webvtt/blob/master/lib/parser.js\n// Parser needs fixing?\nconst content = `WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:${startOffset},LOCAL:00:00:00.000\n\n${printableCues(seg.cues)}\n`;\n const filename = generateSegmentFilename(i);\n result.push({ filename, content });\n });\n\n \n \n return result;\n}\n\nfunction hlsSegmentPlaylist (input, segmentLength) {\n\n const segmented = segment(input, segmentLength);\n\n const printable = printableSegments(segmented);\n const longestSegment = Math.round(findLongestSegment(segmented));\n\n const template = `#EXTM3U\n#EXT-X-TARGETDURATION:${longestSegment}\n#EXT-X-VERSION:3\n#EXT-X-MEDIA-SEQUENCE:0\n#EXT-X-PLAYLIST-TYPE:VOD\n${printable}\n#EXT-X-ENDLIST\n`;\n return template;\n}\n\nfunction pad (num, n) {\n const padding = '0'.repeat(Math.max(0, n - num.toString().length));\n\n return `${padding}${num}`;\n}\n\nfunction generateSegmentFilename (index) {\n return `${index}.vtt`;\n}\n\nfunction printableSegments (segments) {\n const result = [];\n segments.forEach((seg, i) => {\n result.push(`#EXTINF:${seg.duration.toFixed(5)},\n${generateSegmentFilename(i)}`);\n });\n\n return result.join('\\n');\n}\n\nfunction findLongestSegment (segments) {\n let max = 0;\n segments.forEach((seg) => {\n if (seg.duration > max) {\n max = seg.duration;\n }\n });\n\n return max;\n}\n\nfunction printableCues (cues) {\n const result = [];\n cues.forEach((cue) => {\n result.push(printableCue(cue));\n });\n\n return result.join('\\n\\n');\n}\n\nfunction printableCue (cue) {\n const printable = [];\n// if there is an identifer, include it.\n//printable.push\n if (cue.identifier) {\n printable.push(cue.identifier);\n }\n\n const start = printableTimestamp(cue.start);\n const end = printableTimestamp(cue.end);\n\n const styles = cue.styles ? `${cue.styles}` : '';\n\n // always add a space after end timestamp, otherwise JWPlayer will not\n // handle cues correctly\n printable.push(`${start} --> ${end} ${styles}`);\n\n printable.push(cue.text);\n\n return printable.join('\\n');\n}\n\nfunction printableTimestamp (timestamp) {\n const ms = (timestamp % 1).toFixed(3);\n timestamp = Math.round(timestamp - ms);\n const hours = Math.floor(timestamp / 3600);\n const mins = Math.floor((timestamp - (hours * 3600)) / 60);\n const secs = timestamp - (hours * 3600) - (mins * 60);\n\n // TODO hours aren't required by spec, but we include them, should be config\n const hourString = `${pad(hours, 2)}:`;\n return `${hourString}${pad(mins, 2)}:${pad(secs, 2)}.${pad(ms * 1000, 3)}`;\n}\n\nvar WEBVTT3 = hlsSegment(msg.WEBVTT2, 0, 0);// must have child .cues\nmsg.payload=WEBVTT3[0].content\nreturn msg;","outputs":1,"noerr":0,"x":2314,"y":872,"wires":[["74b9713.498ec9","73e14f45.fe9ac"]]},{"id":"74b9713.498ec9","type":"debug","z":"dbbf8510.63c748","name":"WebVTT","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":2676,"y":872,"wires":[]},{"id":"8446bd9b.6571c","type":"function","z":"dbbf8510.63c748","name":"set get Captions","func":"\nvar video_id=msg.video_id;\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\n\n\nvar url = apihost + \"/videos/\" + video_id + \"/captions.json\";\n\n\nvar PutHeader = {\n \"content-type\":\"application/json\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\nmsg.url = url;\nmsg.headers = PutHeader;\n\nreturn msg;","outputs":1,"noerr":0,"x":245,"y":350,"wires":[["9451862f.258878"]]},{"id":"9451862f.258878","type":"http request","z":"dbbf8510.63c748","name":"get SM API call","method":"GET","ret":"obj","url":"","tls":"","x":420,"y":350,"wires":[["56a6ff12.6c5e","44cc54aa.72020c"]]},{"id":"44cc54aa.72020c","type":"function","z":"dbbf8510.63c748","name":"which Caption source field flow.get","func":"\nvar captions = [];\ncaptions= msg.payload.captions;\nvar language_source=flow.get(\"language_source\"); // default source language set in vars\n\nvar translate_field= flow.get(\"translate_field\"); // this must be field type list\nvar caption_id_field = flow.get(\"caption_id_field\");\n//msg.video_download_url = msg.video_object.video_download_url; //need download url\n\n\n\n//captions.json\n\n///*\n// needs to process full job\nif (captions.length>0){\n // found one or more captions\n // get is_default\n \n \n for (i=0; i<captions.length; i++) {\n if (captions[i].is_default === true){\n // are there any listed? This is an array.\n language_source=captions[i].language;\n msg.language_source=language_source;\n return [msg,null]; \n\n }else\n msg.language_source=language_source;\n \n \n \n } return [msg,null]; \n \n}\n\n\n\n\nreturn [null,msg];\n\n","outputs":2,"noerr":0,"x":305,"y":385,"wires":[["f33c0c47.50312","3215d138.d66b6e"],["4c4bbc76.c9bc14"]],"outputLabels":["Translate","None"]},{"id":"f33c0c47.50312","type":"debug","z":"dbbf8510.63c748","name":"source language","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":665,"y":435,"wires":[]},{"id":"4c4bbc76.c9bc14","type":"debug","z":"dbbf8510.63c748","name":"No lang","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":650,"y":465,"wires":[]},{"id":"a7f51934.2a6248","type":"function","z":"dbbf8510.63c748","name":"reset translate field values","func":"var apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id;\nvar translate_field = flow.get(\"translate_field\");\n\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/custom-metadata/{{field_id}}.json //update field\n\n//\n\nvar url = apihost + \"/videos/\" + video_id + \"/custom-metadata/\" + translate_field + \".json\"; // field_id 7906 in IBM Video Streaming. Need configuration capability.\n\n\nvar PutHeader = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\nvar translateText='';\n\nmsg.url = url;\nmsg.method=\"PUT\";\nmsg.headers = PutHeader;\nmsg.payload = \"value=\" + translateText; //\"value=Bubba, Billy, Fred\"; // field_id in SM is Speakers tag list\nmsg.body=\"value=\" + translateText;\nreturn msg;","outputs":1,"noerr":0,"x":1470,"y":555,"wires":[["d4d6582c.55d898"]]},{"id":"6536771d.ac18d8","type":"function","z":"dbbf8510.63c748","name":"set status_log_field value","func":"var apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id;\nvar status_log_field = flow.get(\"status_log_field\");\n//var metadata = [];\n//metadata= msg.payload.metadata;\n\nvar status_log_values=\"\";\nvar myDate = new Date().toISOString();\n\n\nstatus_log_values = flow.get(video_id+\"status_log\");\n\n\nstatus_log_values= status_log_values + myDate + \" Translate start: \"+ msg.translate_model_id + \", \";\n//translateText= \" start translate: \"+ msg.translate_model_id;\n\nflow.set((video_id+\"status_log\"),status_log_values);\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/custom-metadata/{{field_id}}.json //update field\n\n//\n\nvar url = apihost + \"/videos/\" + video_id + \"/custom-metadata/\" + status_log_field + \".json\"; // field_id 7906 in IBM Video Streaming. Need configuration capability.\n\n\nvar PutHeader = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\n\nmsg.url = url;\nmsg.method=\"PUT\";\nmsg.headers = PutHeader;\nmsg.payload = \"value=\" + status_log_values; //\"value=Bubba, Billy, Fred\"; // field_id in SM is Speakers tag list\n//msg.body=\"value=\" + translateText;\nreturn msg;","outputs":1,"noerr":0,"x":1730,"y":525,"wires":[["96eadcbf.f73aa"]]},{"id":"d4d6582c.55d898","type":"http request","z":"dbbf8510.63c748","name":"Update SM field value","method":"use","ret":"txt","url":"","tls":"","x":1470,"y":600,"wires":[["25b87129.8a553e"]]},{"id":"25b87129.8a553e","type":"debug","z":"dbbf8510.63c748","name":"reset traanslate","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1685,"y":645,"wires":[]},{"id":"b654208e.be8e4","type":"delay","z":"dbbf8510.63c748","name":"","pauseType":"delay","timeout":"8","timeoutUnits":"hours","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1715,"y":570,"wires":[["fa0834d3.ce5118"]]},{"id":"fa0834d3.ce5118","type":"function","z":"dbbf8510.63c748","name":"remove flow var","func":"var video_id = msg.video_id;\nflow.set((video_id+\"status_log\"),undefined);\nreturn msg;","outputs":1,"noerr":0,"x":1730,"y":600,"wires":[[]]},{"id":"4e1ffa05.397094","type":"delay","z":"dbbf8510.63c748","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":852.75,"y":755.75,"wires":[["710855b1.59b3bc"]]},{"id":"e00e3ca8.53428","type":"function","z":"dbbf8510.63c748","name":"set status_log_field value","func":"var apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id;\nvar status_log_field = flow.get(\"status_log_field\");\n//var metadata = [];\n//metadata= msg.payload.metadata;\n\nvar status_log_values=\"\";\nvar myDate = new Date().toISOString();\n\n\nstatus_log_values = flow.get(video_id+\"status_log\");\n\n\nstatus_log_values= status_log_values + myDate + \" Translate complete: \"+ msg.translate_model_id + \", \";\n//translateText= \" start translate: \"+ msg.translate_model_id;\n\nflow.set((video_id+\"status_log\"),status_log_values);\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/custom-metadata/{{field_id}}.json //update field\n\n//\n\nvar url = apihost + \"/videos/\" + video_id + \"/custom-metadata/\" + status_log_field + \".json\"; // field_id 7906 in IBM Video Streaming. Need configuration capability.\n\n\nvar PutHeader = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\n\nmsg.url = url;\nmsg.method=\"PUT\";\nmsg.headers = PutHeader;\nmsg.payload = \"value=\" + status_log_values; //\"value=Bubba, Billy, Fred\"; // field_id in SM is Speakers tag list\n//msg.body=\"value=\" + translateText;\nreturn msg;","outputs":1,"noerr":0,"x":575,"y":675,"wires":[["4e1ffa05.397094"]]},{"id":"3215d138.d66b6e","type":"function","z":"dbbf8510.63c748","name":"set status_log_field value per run","func":"// this creates or resets video_id status_log variable.\n// example: 1234567status_log flow varable is set to \"\"\n// this means each run will ensure only the most recent run is recorded \n\n\nvar video_id = msg.video_id;\n\nflow.set((video_id+\"status_log\"),\"\");\n\n\nreturn msg;","outputs":1,"noerr":0,"x":305,"y":415,"wires":[["ffb7fa67.144178"]]},{"id":"c71bf22a.39d18","type":"function","z":"dbbf8510.63c748","name":"status","func":"if (msg.statusCode !=200){\n return [msg,null]\n}else \n\nreturn [null,msg]","outputs":2,"noerr":0,"x":1425,"y":345,"wires":[["9612b8c6.a3b008"],["3a70fe7.b418602"]],"outputLabels":["fail","ok"]},{"id":"9612b8c6.a3b008","type":"function","z":"dbbf8510.63c748","name":"set status_log_field value (fail)","func":"var apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar video_id = msg.video_id;\nvar status_log_field = flow.get(\"status_log_field\");\n//var metadata = [];\n//metadata= msg.payload.metadata;\n\nvar status_log_values=\"\";\nvar myDate = new Date().toISOString();\n\n\nstatus_log_values = flow.get(video_id+\"status_log\");\n\n\nstatus_log_values= status_log_values + myDate + \" Translate failed: can't find caption \"+msg.language_source + \". Check video default captions setting. \";\n//translateText= \" start translate: \"+ msg.translate_model_id;\n\nflow.set((video_id+\"status_log\"),status_log_values);\n\n//https://{{channel_apihost}}/videos/{{VIDEO_ID}}/custom-metadata/{{field_id}}.json //update field\n\n//\n\nvar url = apihost + \"/videos/\" + video_id + \"/custom-metadata/\" + status_log_field + \".json\"; // field_id 7906 in IBM Video Streaming. Need configuration capability.\n\n\nvar PutHeader = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\n\nmsg.url = url;\nmsg.method=\"PUT\";\nmsg.headers = PutHeader;\nmsg.payload = \"value=\" + status_log_values; //\"value=Bubba, Billy, Fred\"; // field_id in SM is Speakers tag list\n//msg.body=\"value=\" + translateText;\nreturn msg;","outputs":1,"noerr":0,"x":1710,"y":335,"wires":[["b6abb1cf.8efb5"]]},{"id":"b6abb1cf.8efb5","type":"link out","z":"dbbf8510.63c748","name":"translate caption NF","links":["fb6f83b7.b1c61","bd21bd87.4673a"],"x":1875,"y":335,"wires":[]},{"id":"fb6f83b7.b1c61","type":"link in","z":"dbbf8510.63c748","name":"translate status write","links":["b6abb1cf.8efb5","96eadcbf.f73aa"],"x":710,"y":735,"wires":[["4e1ffa05.397094"]]},{"id":"5594492.35471b8","type":"debug","z":"dbbf8510.63c748","name":"return Code","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1670,"y":300,"wires":[]},{"id":"47aad573.f12fbc","type":"inject","z":"dbbf8510.63c748","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1035,"y":25,"wires":[["ab9a75d3.27f038","9fdd14e8.3ba7c8","193f4e56.112d52"]]},{"id":"ab9a75d3.27f038","type":"function","z":"dbbf8510.63c748","name":"get Custommetadata Video","func":"var video_id = msg.video_id;\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar language_source = msg.language_source;\n\n\n\n//https://{{channel_apihost}}/custom-metadata-fields.json?filter[type]=video\nvar url = apihost + \"/custom-metadata-fields.json?filter[type]=video\"\n\nvar headers = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\nmsg.method=\"GET\";\nmsg.url = url;\nmsg.headers = headers;\nmsg.payload={};\n\nreturn msg;","outputs":1,"noerr":0,"x":1430,"y":30,"wires":[["943a9079.72a2b"]]},{"id":"9fdd14e8.3ba7c8","type":"function","z":"dbbf8510.63c748","name":"get Channel list","func":"var video_id = msg.video_id;\nvar apihost = flow.get(\"SMapihost\"); //SM hostURL\nvar access_token= flow.get(\"access_token\");\nvar language_source = msg.language_source;\n\n\nvar url = apihost + \"/users/self/channels.json\"\n\nvar headers = {\n \"content-type\":\"application/x-www-form-urlencoded\",\n \"Authorization\":\"Bearer \" + access_token,\n \"Accepts\": \"application/json\"\n\n };\n\nmsg.method=\"GET\";\nmsg.url = url;\nmsg.headers = headers;\nmsg.payload={};\n\nreturn msg;","outputs":1,"noerr":0,"x":1395,"y":63,"wires":[["58bc3a72.4b08a4"]]},{"id":"5ceed2d1.f664ec","type":"debug","z":"dbbf8510.63c748","name":"Metadata fields","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1955,"y":30,"wires":[]},{"id":"f457786e.d56828","type":"debug","z":"dbbf8510.63c748","name":"Channel List","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1945,"y":60,"wires":[]},{"id":"943a9079.72a2b","type":"http request","z":"dbbf8510.63c748","name":"get metatdata fields","method":"use","ret":"obj","url":"","tls":"","x":1675,"y":30,"wires":[["5ceed2d1.f664ec"]]},{"id":"58bc3a72.4b08a4","type":"http request","z":"dbbf8510.63c748","name":"get Channel list","method":"use","ret":"obj","url":"","tls":"","x":1660,"y":60,"wires":[["f457786e.d56828"]]},{"id":"919190ba.9d283","type":"link in","z":"dbbf8510.63c748","name":"SM update (PUT)","links":["80322ae7.322328"],"x":935,"y":755,"wires":[["710855b1.59b3bc"]]},{"id":"96eadcbf.f73aa","type":"link out","z":"dbbf8510.63c748","name":"translate status field","links":["fb6f83b7.b1c61"],"x":1890,"y":525,"wires":[]},{"id":"a540bd44.d2a4f","type":"comment","z":"dbbf8510.63c748","name":"Translate API call","info":"This line is the call to tranlate API.\n\nNeed to convert apikey to Basic token\n\nbase64_encode(apikey:<apikey>)\nhttps://cloud.ibm.com/docs/iam?topic=iam-iamapikeysforservices\n","x":2090,"y":595,"wires":[]},{"id":"193f4e56.112d52","type":"function","z":"dbbf8510.63c748","name":"api key to token base64 encode","func":"/**\n * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].\n * As per RFC 4648, no newlines are added.\n *\n * Characters in str must be within ISO-8859-1 with Unicode code point <= 256.\n *\n * Can be achieved JavaScript with btoa(), but this approach may be useful in other languages.\n *\n * @param {string} str ASCII/ISO-8859-1 string to be encoded as base-64.\n * @returns {string} Base64-encoded string.\n * \n * https://gist.github.com/chrisveness/e121cffb51481bd1c142\n */\nfunction Base64Encode(str) {\n if (/([^\\u0000-\\u00ff])/.test(str)) throw Error('String must be ASCII');\n\n var b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c;\n\n c = str.length % 3; // pad string to length of multiple of 3\n if (c > 0) { while (c++ < 3) { pad += '='; str += '\\0'; } }\n // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars\n\n for (c=0; c<str.length; c+=3) { // pack three octets into four hexets\n o1 = str.charCodeAt(c);\n o2 = str.charCodeAt(c+1);\n o3 = str.charCodeAt(c+2);\n\n bits = o1<<16 | o2<<8 | o3;\n\n h1 = bits>>18 & 0x3f;\n h2 = bits>>12 & 0x3f;\n h3 = bits>>6 & 0x3f;\n h4 = bits & 0x3f;\n\n // use hextets to index into code string\n e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);\n }\n str = e.join(''); // use Array.join() for better performance than repeated string appends\n\n // replace 'A's from padded nulls with '='s\n str = str.slice(0, str.length-pad.length) + pad;\n\n return str;\n}\n\n/**\n * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648].\n * As per RFC 4648, newlines are not catered for.\n *\n * Can be achieved JavaScript with atob(), but this approach may be useful in other languages.\n *\n * @param {string} str Base64-encoded string.\n * @returns {string} Decoded ASCII/ISO-8859-1 string.\n */\nfunction Base64Decode(str) {\n if (!(/^[a-z0-9+/]+={0,2}$/i.test(str)) || str.length%4 != 0) throw Error('Not base64 string');\n\n var b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n var o1, o2, o3, h1, h2, h3, h4, bits, d=[];\n\n for (var c=0; c<str.length; c+=4) { // unpack four hexets into three octets\n h1 = b64.indexOf(str.charAt(c));\n h2 = b64.indexOf(str.charAt(c+1));\n h3 = b64.indexOf(str.charAt(c+2));\n h4 = b64.indexOf(str.charAt(c+3));\n\n bits = h1<<18 | h2<<12 | h3<<6 | h4;\n\n o1 = bits>>>16 & 0xff;\n o2 = bits>>>8 & 0xff;\n o3 = bits & 0xff;\n\n d[c/4] = String.fromCharCode(o1, o2, o3);\n // check for padding\n if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2);\n if (h3 == 0x40) d[c/4] = String.fromCharCode(o1);\n }\n str = d.join(''); // use Array.join() for better performance than repeated string appends\n\n}\n\n//var string = 'apikey:KV02SOFCzBJi3tlpQ2TRPvpEOTa2o__ZctEtRby3WtIq';\n//LXI5CFFY0CDE47xnm2TsxN-2dUmcPOekRzp8LdSiQ16O\nvar string = \"apikey:\" + flow.get(\"translate_apikey\"); \nmsg.payload= Base64Encode(string);\nreturn msg;","outputs":1,"noerr":0,"x":1710,"y":95,"wires":[["906c4a58.976298"]]},{"id":"906c4a58.976298","type":"debug","z":"dbbf8510.63c748","name":"translate_token","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1955,"y":90,"wires":[]},{"id":"eb7a38c4.677648","type":"function","z":"dbbf8510.63c748","name":"WEBVTT Parser MIT v2","func":"// source: https://github.com/osk/node-webvtt/blob/master/lib/parser.js\n// MIT license\n//Updated Regex to include comma in subsecond time part\n// Burton Boucher 20190910\n// [email protected]\n\n/**\n * See spec: https://www.w3.org/TR/webvtt1/#file-structure\n */\nvar e;\n\nfunction ParserError (message, error) {\n this.message = message;\n this.error = error;\n}\n\n//const { message, error } =ParserError.prototype = Object.create(Error.prototype);\n\n\n//const TIMESTAMP_REGEXP = /([0-9]{1,2})?:?([0-9]{2}):([0-9]{2}\\.[0-9]{2,3})/;\nconst TIMESTAMP_REGEXP = /([0-9]{1,2})?:?([0-9]{2}):([0-9]{2}[\\.\\,][0-9]{2,3})/; // optional comma\n\nfunction parse (input, options) {\n if (!options) {\n options = {};\n }\n\n const { meta = false, strict = true } = options;\n\n if (typeof input !== 'string') {\n e= new Error('Input must be a string');\n throw e;\n }\n\n input = input.trim();\n input = input.replace(/\\r\\n/g, '\\n');\n //input = input.replace(/\\n[A-Z|a-z|\\d]/g, ' ');\n input = input.replace(/\\r/g, '\\n');\n\n const parts = input.split('\\n\\n');\n const header = parts.shift();\n\n\n\n\n if (!header.startsWith('WEBVTT')) {\n //throw new ParserError('Must start with \"WEBVTT\"');\n e = new Error('Must start with \"WEBVTT\"');\n throw e;\n }\n\n const headerParts = header.split('\\n');\n\n const headerComments = headerParts[0].replace('WEBVTT', '');\n\n if (headerComments.length > 0 && (headerComments[0] !== ' ' && headerComments[0] !== '\\t')\n ) {\n throw new ParserError('Header comment must start with space or tab');\n }\n\n // nothing of interests, return early\n if (parts.length === 0 && headerParts.length === 1) {\n return { valid: true, strict, cues: [], errors: [] };\n }\n\n if (!meta && headerParts.length > 1 && headerParts[1] !== '') {\n throw new ParserError('Missing blank line after signature');\n }\n\n const { cues, errors } = parseCues(parts, strict);\n\n if (strict && errors.length > 0) {\n throw errors[0];\n }\n\n const headerMeta = meta ? parseMeta(headerParts) : null;\n\n const result = { valid: errors.length === 0, strict, cues, errors };\n\n if (meta) {\n result.meta = headerMeta;\n }\n\n return result;\n}\n\nfunction parseMeta (headerParts) {\n const meta = {};\n headerParts.slice(1).forEach(header => {\n const [key, value] = header.split(':').map(t => t.trim());\n meta[key] = value;\n });\n return Object.keys(meta).length > 0 ? meta : null;\n}\n\n\nfunction parseCues (cues, strict) {\n const errors = [];\n\n const parsedCues = cues\n .map((cue, i) => {\n try {\n return parseCue(cue, i, strict);\n } catch (e) {\n errors.push(e);\n return null;\n }\n })\n .filter(Boolean);\n\n return {\n cues: parsedCues,\n errors\n };\n}\n\n\n/**\n * Parse a single cue block.\n *\n * @param {array} cue Array of content for the cue\n * @param {number} i Index of cue in array\n *\n * @returns {object} cue Cue object with start, end, text and styles.\n * Null if it's a note\n */\nfunction parseCue (cue, i, strict) {\n let identifier = \"\";\n let pause_on_exit=false;\n let region=null;\n let direction=\"horizontal\";\n let snap_to_lines=true;\n let line=\"auto\";\n let line_alignment=\"start\";\n let position=\"auto\";\n let size=100;\n let text_alignment=\"center\";\n let start = 0;\n let end = 0.01;\n let text = \"\";\n let styles = \"\";\n\n // split and remove empty lines\n const lines = cue.split('\\n').filter(Boolean);\n\n if (lines.length > 0 && lines[0].trim().startsWith('NOTE')) {\n return null;\n }\n\n if (lines.length === 1 && !lines[0].includes('-->')) {\n //throw new ParserError(`Cue identifier cannot be standalone (cue #${i})`);\n e= new Error(`Cue identifier cannot be standalone (cue #${i})`);\n throw e;\n }\n\n if (lines.length > 1 &&\n !(lines[0].includes('-->') || lines[1].includes('-->'))) {\n const msg = `Cue identifier needs to be followed by timestamp (cue #${i})`;\n //throw new ParserError(msg);\n e= new Error(msg);\n throw e;\n \n }\n\n if (lines.length > 1 && lines[1].includes('-->')) {\n identifier = lines.shift();\n }\n\n const times = lines[0].split(' --> ');\n\n if (times.length !== 2 ||\n !validTimestamp(times[0]) ||\n !validTimestamp(times[1])) {\n //throw new ParserError(`Invalid cue timestamp (cue #${i})`);\n e= new Error(`Invalid cue timestamp (cue #${i})`);\n throw e;\n }\n\n start = parseTimestamp(times[0]);\n end = parseTimestamp(times[1]);\n\n if (strict) {\n if (start > end) {\n // throw new ParserError(`Start timestamp greater than end (cue #${i})`);\n e= new Error(`Start timestamp greater than end (cue #${i})`);\n throw e;\n \n }\n\n if (end <= start) {\n // throw new ParserError(`End must be greater than start (cue #${i})`);\n e= new Error(`End must be greater than start (cue #${i})`);\n throw e;\n \n }\n }\n\n if (!strict && end < start) {\n //throw new ParserError(`End must be greater or equal to start when not strict (cue #${i})`);\n e= new Error(`End must be greater or equal to start when not strict (cue #${i})`);\n throw e;\n\n }\n\n // TODO better style validation\n styles = times[1].replace(TIMESTAMP_REGEXP, '').trim();\n\n lines.shift();\n\n text = lines.join('\\n');\n\n if (!text) {\n return false;\n }\n// not all configured. 20190913 burton boucher\n return { identifier,region,direction,snap_to_lines,line,line_alignment,position,size,text_alignment, start, end, text, styles };\n}\n\n\nfunction validTimestamp (timestamp) {\n return TIMESTAMP_REGEXP.test(timestamp);\n}\n\nfunction parseTimestamp (timestamp) {\n const matches = timestamp.match(TIMESTAMP_REGEXP);\n // correct for comma in some tmestamps. Comma kills millseconds in calc burton boucher 20190928\n let secs= parseFloat((matches[3]).replace(\",\",\".\"));\n //let secs = parseFloat(matches[3]);\n secs += parseFloat(matches[2]) * 60; // mins\n secs += parseFloat(matches[1] || 0) * 60 * 60; // hours\n // secs += parseFloat(matches[4]);\n return secs;\n}\n\n//var WEBVTT=msg.payload;\nvar WEBVTT=msg.WEBVTT; // from base test.\n\n//var test1;\n//test1=parse(WEBVTT, {meta: true, strict:false });\nmsg.sourceLanguage=parse(WEBVTT, {meta: true, strict:false });\nreturn msg;","outputs":1,"noerr":0,"x":2334,"y":424,"wires":[["2a6380e5.5f91c","b0345735.8c7898"]]},{"id":"4a121c62.be9474","type":"function","z":"dbbf8510.63c748","name":"sentences chunk split","func":"var sentences = [];\nvar blocks=[];\nsentences = msg.payload; //20200324\nvar ncount = sentences.length;\nvar splitSize=4400; // split playload size\nvar sentencePos=0; // last cue position in sentences\nvar sentencesSize=0;\n//msg.payload={};\nmsg.parts = {};\nmsg.parts.id = RED.util.generateId();\nmsg.parts.type = \"array\";\n\nvar count = 0;\nvar testPOS=0;\n\n\n// best practice is to split 4-4.5K for IBM Language Translator. \n/* Design is to use IBM Language Translator API using array input method where each element contains one cue.\nRelies upon IBM Language Translator to provide all sentence segmentation and to properly return translation to each cue\n*/\n\n/* What's needed:\n1. initialize. splitSize, set last sentencePos=0\n2. loop through cues array\n2.1 get sentence.length set to sentenceSize sentencePos ++\n2.2 When sentenceSize > splitSize set sentencePos = sentencePos +1, return message split\n2.3 when end of sentences last split (partial)\n*/\n//\n\nfor (var ict = 0; ict < ncount; ict++){\n sentencesSize=sentencesSize + sentences[ict].length;\n if (sentencesSize > splitSize) {\n msg.parts.index = count; // sets order of how msg will be joined\n msg.parts.ch=\"\";\n// msg.parts.count=ncount;\n blocks.push(sentences.slice(sentencePos,ict+1));\n msg.payload=blocks;\n \n sentencePos=ict+1;\n count=count+1;\n //msg.sentencesSize=sentencesSize;\n sentencesSize=0;\n //msg.sentencePos=sentencePos;\n node.send(RED.util.cloneMessage(msg));\n blocks=[];\n }else if (ncount < ict+2 ){\n msg.parts.index = ict+1; // sets order of how msg will be joined\n msg.parts.index = count;\n msg.parts.ch=\"\";\n// msg.parts.count=ncount;\n blocks.push(sentences.slice(sentencePos,ict+1));\n msg.payload=blocks;\n // msg.sentencesSize=sentencesSize;\n // msg.ict=ict;\n msg.complete=true; // this is used to signal Join we are ready to assemble split messages.See var ncount above.\n // send\n node.send(RED.util.cloneMessage(msg));\n\n }\n\n}\n\n\n\n\n\n\n//return msg;","outputs":1,"noerr":0,"x":2324,"y":488,"wires":[["fe10dcbe.f3409","2082c7d3.5394d8"]]},{"id":"fe10dcbe.f3409","type":"debug","z":"dbbf8510.63c748","name":"chunked","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":2564,"y":496,"wires":[]},{"id":"b02b4208.a3869","type":"join","z":"dbbf8510.63c748","name":"de chunk","mode":"auto","build":"merged","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"5","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":2284,"y":648,"wires":[["69a1c04f.cb51d","826996c5.ff3768"]]},{"id":"69a1c04f.cb51d","type":"debug","z":"dbbf8510.63c748","name":"dechunked ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":2678,"y":648,"wires":[]},{"id":"f5bd1ae.93228e8","type":"debug","z":"dbbf8510.63c748","name":"flatten2","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2668,"y":616,"wires":[]},{"id":"c6e37940.6bd438","type":"function","z":"dbbf8510.63c748","name":"segmenter raw","func":"var strict=true;\n\n//const parse = require('./parser').parse;\n\nfunction segment (input, segmentLength) {\n segmentLength = segmentLength || 10;\n\n// const parsed = parse(input);\n const parsed = input;\n \n const segments = [];\n\n let cues = [];\n let queuedCue = null;\n let currentSegmentDuration = 0;\n let totalSegmentsDuration = 0;\n\n /**\n * One pass segmenting of cues\n */\n parsed.cues.forEach((cue, i) => {\n const firstCue = i === 0;\n const lastCue = i === parsed.cues.length - 1;\n const start = cue.start;\n const end = cue.end;\n const nextStart = lastCue ? Infinity : parsed.cues[i + 1].start;\n const cueLength = firstCue ? end : end - start;\n const silence = firstCue ? 0 : (start - parsed.cues[i - 1].end);\n\n currentSegmentDuration = currentSegmentDuration + cueLength + silence;\n\n debug('------------');\n debug(`Cue #${i}, segment #${segments.length + 1}`);\n debug(`Start ${start}`);\n debug(`End ${end}`);\n debug(`Length ${cueLength}`);\n debug(`Total segment duration = ${totalSegmentsDuration}`);\n debug(`Current segment duration = ${currentSegmentDuration}`);\n debug(`Start of next = ${nextStart}`);\n\n // if there's a boundary cue queued, push and clear queue\n if (queuedCue) {\n cues.push(queuedCue);\n currentSegmentDuration += queuedCue.end - totalSegmentsDuration;\n queuedCue = null;\n }\n\n cues.push(cue);\n\n // if a cue passes a segment boundary, it appears in both\n let shouldQueue = nextStart - end < segmentLength &&\n silence < segmentLength &&\n currentSegmentDuration > segmentLength;\n\n if (shouldSegment(totalSegmentsDuration, segmentLength, nextStart,\n silence)) {\n\n const duration = segmentDuration(lastCue, end, segmentLength,\n currentSegmentDuration,\n totalSegmentsDuration);\n\n segments.push({ duration, cues });\n\n totalSegmentsDuration += duration;\n currentSegmentDuration = 0;\n cues = [];\n } else {\n shouldQueue = false;\n }\n\n if (shouldQueue) {\n queuedCue = cue;\n }\n });\n\n return segments;\n}\n\nfunction shouldSegment (total, length, nextStart, silence) {\n\n // this is stupid, but gets one case fixed...\n const x = alignToSegmentLength(silence, length);\n const nextCueIsInNextSegment = silence <= length ||\n x + total < nextStart;\n\n return nextCueIsInNextSegment && nextStart - total >= length;\n}\n\nfunction segmentDuration (lastCue, end, length, currentSegment, totalSegments) {\n let duration = length;\n\n if (currentSegment > length) {\n duration = alignToSegmentLength(currentSegment - length, length);\n }\n\n // make sure the last cue covers the whole time of the cues\n if (lastCue) {\n duration = parseFloat((end - totalSegments).toFixed(2));\n } else {\n duration = Math.round(duration);\n }\n\n return duration;\n}\n\nfunction alignToSegmentLength (n, segmentLength) {\n n += segmentLength - n % segmentLength;\n return n;\n}\n\nconst debugging = false;\n\n/* istanbul ignore next */\nfunction debug (m) {\n if (debugging) {\n console.log(m);\n }\n}\n//msg.WEBVTT2= segment(msg.sentences, 7200);\nmsg.WEBVTT2= segment(msg.payload, 7200);\n//msg.WEBVTT2= segment(msg.outCueTest, 7200);\nreturn msg;","outputs":1,"noerr":0,"x":2304,"y":840,"wires":[["4e79d250.e1f08c"]]},{"id":"2082c7d3.5394d8","type":"delay","z":"dbbf8510.63c748","name":"","pauseType":"rate","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"5","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":2304,"y":520,"wires":[["58eec2a5.c9405c"]]},{"id":"1932afff.8d91f","type":"http request","z":"dbbf8510.63c748","name":"POST translate call","method":"POST","ret":"obj","url":"","tls":"","x":2498,"y":584,"wires":[["28863423.43fb6c","a713eaf5.71eef8"]]},{"id":"28863423.43fb6c","type":"debug","z":"dbbf8510.63c748","name":"raw text","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":2668,"y":584,"wires":[]},{"id":"22f9e427.77d46c","type":"debug","z":"dbbf8510.63c748","name":"chunked","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2668,"y":552,"wires":[]},{"id":"58eec2a5.c9405c","type":"function","z":"dbbf8510.63c748","name":"Flatten Array v2","func":"//Flatten Array v2. Switched to concat from mozilla .flat\nvar arrayToFlatten = msg.payload;\nvar flattenedArray = [].concat.apply([], arrayToFlatten);\nmsg.payload=flattenedArray\n\nreturn msg;","outputs":1,"noerr":0,"x":2304,"y":552,"wires":[["47badcd0.abbfb4"]]},{"id":"c994f6.bc553b08","type":"debug","z":"dbbf8510.63c748","name":"flatten3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2668,"y":680,"wires":[]},{"id":"2a6380e5.5f91c","type":"debug","z":"dbbf8510.63c748","name":"parser","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":2554,"y":416,"wires":[]},{"id":"b0345735.8c7898","type":"function","z":"dbbf8510.63c748","name":"get cueParts tokenize","func":"\n//((?![.?!][’\"]?\\s[\"’]?[A-Z][^.?!]).)\n//sentenceFound= cue.text.match(/[\"’]?[\\d|A-Z][^.?!]+((?![.?!][’\"]?\\s[\"’]?[A-Z][^.?!]).)+[.?!’\"]+/g);\n//sentenceFound= cue.text.match(/[\"’]?[\\d|A-Z][^.?!]+((?![.?!][’\"]?\\s[\"’]?[A-Z][^.?!]).)+[.?!’\"]+/g);\n \n \n //sentenceFound= text.match(/((?![.?!][’\"]?\\s[\"’]?[A-Z][^.?!]).)+/g);\n\n\n\n// these are for output from WebVTT parser - cues\n// We need to add cueparts. Full sentences plus any trailing. Zero or more sentences\n\n\n\n\n\nfunction countWords (value, index, array) {\nconst errors = [];\n//WebVTT cue variables\nlet identifier = \"\";\nlet region =\"\";\nlet direction = \"horizontal\";\nlet snapToLines = true;\nlet alignment=\"middle\";\nlet linePosition=\"auto\";\nlet line_alignment=\"start\";\nlet position=\"auto\";\nlet styles=\"\";\nlet size = 100;\nlet start = 0;\nlet end = 0.01;\nlet pauseOnExit= false;\nlet textPosition=50;\nlet id = \"\";\nvar text ;\n\n\n\n\n//additional variables//\nlet language ='en-US';\n// future. Not using tokens today. requires more power such as NLU or dictionary \nlet tokenCount=0; // tokenCount is different by language. Most particualy Chinese, Korean, Japanese (no space bewteen char and multiple chars can be a token)\nlet tokenMin=130; // not used. May be used in future. Tokens per min.\n\nlet wordCount = 0;\nlet charCount=0;\nlet textLength=0;\nlet fullStop = -1;\nlet sentenceIndex=-1;\nlet firstNonSentence = true;\n\n\n//cueParts \nlet cuePartText = \"\";\nlet isContainFullstop= false;\nvar tempTextLength=0;\nvar cueParts=[]; // to be included in object it should be array\nvar cuepart={};\nvar sentenceChars=0;\n//styles=cue.styles;\n\nvar i;\n\nfunction updateCuePartSentenceFound(value, index, array) {\n isContainFullstop=true;\n cuePartText=value.replace(/\\n/g,\" \");\n charCount = cuePartText.length;\n wordCount = cuePartText.split(' ').length;\n sentenceChars = sentenceChars + charCount;\n //cuepart={ cueIndex, cuePartText, isContainFullstop, wordCount, charCount }; \n \n\n // sentenceFound.push(cuepart);\n // return { cuePartText, isContainFullstop, wordCount, charCount };\n\n cueParts[index]={ cueIndex, cuePartText, isContainFullstop, tokenCount, wordCount, charCount };\n return sentenceChars;\n}\n\n\ncueIndex =i;\n\nstart=value.start;\nend=value.end;\nstyles=value.styles;\nline_alignment=value.line_alignment;\n\ntext = value.text;\n //sentenceFound= text.match(/((?![.?!][’\"]?\\s[\"’]?[A-Z][^.?!]).)+/g);\n // added \\s\\S to include any char including . period to allow ignoring newline char. Might still work if this section was moved to end. The issue \n\n\n\n//cuePartText=text.replace(/\\n/g,\" \");\n//cueParts= text.match(/(\\? |\\?|\\! |\\! |\\. |\\.)+/g);\ncueParts= text.match(/[\"’]?[\\d|A-Z|a-z][^.?!]+((?![.?!][’\"]?\\s[\"’]?[A-Z][^.?!])[\\s\\S])+[.?!’\"]+/g);\n\n\n\n if (cueParts ===null){\n isContainFullstop=false;\n if (text.startsWith(\"[\") && text.endsWith(\"]\") ){\n isContainFullstop=true; \n } \n cuePartText=text.replace(/\\n/g,\" \"); \n charCount = cuePartText.length;\n wordCount = cuePartText.split(' ').length;// removed +1\n tokenCount = 0;\n cuepart={ cueIndex, cuePartText, isContainFullstop, tokenCount, wordCount, charCount }; \n \n cueParts=[];\n \n cueParts.push(cuepart);\n //return { cuePartText, isContainFullstop, tokenCount, wordCount charCount };\n } else {\n cueParts.forEach(updateCuePartSentenceFound);\n // get the rest of the text; get char count (total cue char count - all sentences found char count)\n //charCount = charCount-cueParts.join('').length;\n sentence = cueParts.join(' ') ; \n charCount=sentence.length;\n charCount=sentenceChars;\n if (charCount<text.length){\n isContainFullstop=false;\n if (text.startsWith(\"[\") && text.endsWith(\"]\") ){\n isContainFullstop=true; \n } \n //charCount = charCount-sentenceFound.join('').length;\n cuePartText=text.substring((charCount+1)).trim();\n cuePartText=cuePartText.replace(/\\n/g,\" \"); \n charCount = cuePartText.length;\n wordCount = cuePartText.split(' ').length;\n tokenCount =0;\n cuepart={ cueIndex, cuePartText, isContainFullstop, tokenCount, wordCount, charCount, sentenceChars }; \n cueParts.push(cuepart);\n sentenceChars=0;\n }\n // need to find if there is a partial trailing sentence part\n\n\n }\n// now get token(word for english) count for each of sentences / partial sentence.\n \n \n // text=text.replace(\"\\n\",\" \"); //0928\n \n //wordCount=cue.text.split(' ').length;\n // wordCount=text.split(' ').length; //0928 \n//sentenceFound= text.match(/(\\? |\\?|\\! |\\! |\\. |\\.)+/g);\n//sentenceFound= text.match(/(\\? |\\?|\\! |\\! |\\. |\\.)+/);\n\n newCueParts.push( { identifier, start, end, pauseOnExit,direction,snapToLines,linePosition,textPosition,size, alignment, text, styles, wordCount, textLength, fullStop, language, cueParts });\n \n\n\n} \n\n\n\n\n\n\nstrict=true;\n//var sourceCuesParts = countWords(cues, strict);\n\nvar newCueParts=[];\n//msg.cueParts= sourceCuesParts;\nvar sentenceChars=0;\nvar cues=msg.sourceLanguage.cues;\n//msg.cues=cues;//20200324\ncues.forEach(countWords);\nmsg.payload= newCueParts;\nreturn msg;","outputs":1,"noerr":0,"x":2324,"y":456,"wires":[["229ec972.700876","4b7f8db4.5f35c4"]]},{"id":"229ec972.700876","type":"debug","z":"dbbf8510.63c748","name":"cueParts in payload","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2956,"y":448,"wires":[]},{"id":"4b7f8db4.5f35c4","type":"function","z":"dbbf8510.63c748","name":"get senteces","func":"function createSentences(value, index, array){\n // goal is to create object sentence:\n // .text\n // .cueIndex\n // .cuePart\n // .numTokens\n // .numWords\n // .language\n // .numChars\n // Will assemble sentence from 1 or more cueParts. A cuePart contains one or more sentence, a partial sentence or both. \n // cuePart parent is a cue. Cue can have 1 or more cueParts\n // \n // note one char will get added to sentence object.numChars for each additional cuePartText. A space is added. Easier to consider ater the fact\n let text =\"\";\n let cueIndex=0;\n //let cuePart=[];\n let numTokens=0;\n let numWords=0\n let numChars=0\n let language=\"\";\n\n\n \n \n cueIndex=index;\n var icuePart=0;\n var cuePartItem;\n var tokenCount=0;\n var wordCount=0\n var charCount=0;\n var isContainFullstop=false;\n var cuePartIndex=0;\n for (ipart=0; ipart < value.cueParts.length; ipart++){ \n if (value.cueParts[ipart].isContainFullstop){\n // sentence full stop\n // sentence text = temp text + cuePartText\n //var cuepartText=value.cueParts[ipart].cuePartText;\n \n wordCount = value.cueParts[ipart].wordCount;\n charCount = value.cueParts[ipart].charCount;\n isContainFullstop = value.cueParts[ipart].isContainFullstop;\n cuePartIndex=ipart;\n text = tmpText + value.cueParts[ipart].cuePartText;\n cuePartText=value.cueParts[ipart].cuePartText;\n language=value.language;\n numTokens=0; // bb 03132020 text.split(' ').length;\n numWords=text.split(' ').length;\n numChars=text.length;\n cuePart.push({cuePartText, cueIndex, cuePartIndex, tokenCount, wordCount, charCount, isContainFullstop});\n \n sentences.push({ text, cueIndex, cueParts: cuePart, numTokens, numWords, numChars, language });\n tmpText=\"\";\n tmpcuePart=[];\n cuePart=[];\n\n }else {\n // tmpText = tmpText +' '+cue.cueParts[ipart].cuePartText\n tmpText = tmpText + value.cueParts[ipart].cuePartText + \" \";\n wordCount = value.cueParts[ipart].wordCount;\n charCount = value.cueParts[ipart].charCount;\n isContainFullstop = value.cueParts[ipart].isContainFullstop;\n cuePartIndex=ipart;\n cuePartText = tmpText;\n // if the last cue does not have a full stop process as if it does. Don't want to lose text due to punctuation.\n if (cueIndex==array.length-1){\n \n wordCount = value.cueParts[ipart].wordCount;\n charCount = value.cueParts[ipart].charCount;\n isContainFullstop = value.cueParts[ipart].isContainFullstop;\n cuePartIndex=ipart;\n text = tmpText;// + value.cueParts[ipart].cuePartText;\n cuePartText=value.cueParts[ipart].cuePartText;\n language=value.language;\n numWords=text.split(' ').length;\n numChars=text.length;\n\n cuePart.push({cuePartText, cueIndex, cuePartIndex, tokenCount, wordCount, charCount, isContainFullstop});\n sentences.push({ text, cueIndex, cueParts: cuePart, numWords, numChars, language });\n }else {\n cuePart.push({cuePartText, cueIndex, cuePartIndex, tokenCount, wordCount, charCount, isContainFullstop});\n }\n\n \n } \n }\n\n \n}\nvar sentences=[];\nvar tmpText=\"\";\nlet cuePart=[];\nvar cues=msg.payload;\n//20200324msg.cues = cues;//test\ncues.forEach(createSentences)\n//msg.sourceSentences = cues.forEach(createSentences); \nmsg.newSentence=sentences;// need to build this map function\nconst sentencesText = sentences.map(sentence => sentence.text);\n//20200324msg.mysentences=sentencesText;\nmsg.payload=sentencesText; // flat array of sentences\nreturn msg;","outputs":1,"noerr":0,"x":2510,"y":456,"wires":[["2f9f808d.ce41d","4a121c62.be9474"]]},{"id":"2f9f808d.ce41d","type":"debug","z":"dbbf8510.63c748","name":"sentences new","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2704,"y":456,"wires":[]},{"id":"58aff479.46e67c","type":"function","z":"dbbf8510.63c748","name":"Copy translation into new sentence based upon sentences.cueparts","func":"function insertTranslation(value,index,arr ){\n let numChars=value.translation.length;\n var tmpWords =value.translation.split(' ');\n let numWords=value.translation.split(' ').length;\n let numTokens=0;\n let wordBasedToken=true;\n var tmpTextValue = value.translation;\n var cuePartTokenCount=0;\n var cuePartWordCount=0;\n var xlateTokenRatio\n let xlatetarget=msg.translate_model_id;\n sentenceAndCuePart[index].xlateText = tmpTextValue;\n if (numWords==numChars||numWords==1 || xlatetarget==\"en-zh\" ||\"en-zh-TW\"){\n numWords = numChars;\n wordBasedToken=false;\n } else {\n numWords = numWords;\n }\n sentenceAndCuePart[index].xlateNumTokens = numTokens; \n sentenceAndCuePart[index].xlatenumWords = numWords; //tmpTextValue.split(' ').length;\n sentenceAndCuePart[index].xlateNumChars = numChars;\n sentenceAndCuePart[index].xlatelanguage = msg.translate_model_id;\n // calc token ratio. Source language tokens divided by translated number of tokens. \n // if (sentenceAndCuePart[index].numWords<sentenceAndCuePart[index].xlatenumWords){\n // xlateTokenRatio = sentenceAndCuePart[index].numWords/sentenceAndCuePart[index].xlatenumWords;\n // }else{\n //use numWords to calculate ratio. Not really correct except but the best we can do without NLU || dictionary,..\n xlateTokenRatio = sentenceAndCuePart[index].xlatenumWords / sentenceAndCuePart[index].numWords;\n // }\n \n sentenceAndCuePart[index].xlateTokenRatio = xlateTokenRatio;\n var cueParts = sentenceAndCuePart[index].cueParts;\n if (cueParts.length>1){\n for (i=0;i< cueParts.length; i++){\n if (i == cueParts.length -1){\n // the rest of text goes here. May be more than calculated \n cuePartwordCount = tmpWords.length;\n }else{\n cuePartwordCount =cueParts[i].wordCount*xlateTokenRatio;\n } \n cueParts[i].xlatecuewordCount = cuePartwordCount;\n if (wordBasedToken){\n // will need to seperate out for language support. Some languages don't use spaces between tokens\n cueParts[i].xlatecuePartText = tmpWords.slice(0,cuePartwordCount).join(' '); // No for Hanj languages \n }else{\n //tmpWords = value.translation; // Character based rather than word based so get chars. Chinese for example\n tmpWords = tmpTextValue;//03242002\n cueParts[i].xlatecuePartText = tmpWords.substr(0,cuePartwordCount);\n }\n \n //03242002 tmpWords = tmpWords.slice(cuePartwordCount);\n tmpTextValue = tmpTextValue.slice(cuePartwordCount); //03242002\n \n } \n }else{\n cueParts[0].xlatecuePartText = value.translation;\n cueParts[0].xlatecueTokenCount = numTokens;\n cueParts[0].xlatecueWordCount = numWords;\n cueParts[0].xlatecueCharCount = numChars;\n \n }\n \n\n}\n\nfunction insertCueParts(value,index,arr){\n \n}\n\n\n\nvar tranlatedSentences=msg.payload;\nvar sentenceAndCuePart=msg.newSentence;\n//create a new object with translated text? or just alter the one that's there?\n// phase 1 for each translatedSentences copy to ... lets use same object and add additional properties.\ntranlatedSentences.forEach(insertTranslation);\nsentenceAndCuePart.forEach(insertCueParts);\n\n//msg.sentenceAndCueParts=sentenceAndCuePart;\nmsg.payload=sentenceAndCuePart;\n\nreturn msg;","outputs":1,"noerr":0,"x":2474,"y":712,"wires":[["ba66a814.025a78"]]},{"id":"80114ff.5ab5eb","type":"function","z":"dbbf8510.63c748","name":"map xlat sentence into new sentences. cueparts","func":"\nfunction getCues(value, index, arr){\n // looping throw sentences.cueParts. \n justCueParts.push(value.cueParts.slice(0));\n}\n\n\nfunction updateCues(value, index, arr){\n sourceLanguage2.cues[value.cueIndex].text =value.xlatecuePartText\n}\n\nvar sourceLanguage2 =msg.sourceLanguage; //sourcelanguage is original making a copy\n//var sentenceAndCueParts=msg.sentenceAndCueParts;\nvar sentenceAndCueParts=msg.payload;\nvar justCueParts = [];\nvar justCuesParts2=[];\n// get cues. extract from sentences.cueParts\nsentenceAndCueParts.forEach(getCues);\n// flatten cueParts array\njustCuesParts2=justCueParts.flat(Infinity);\n// now update the original cues object\njustCuesParts2.forEach(updateCues);\n\n\n//msg.justCueParts=justCueParts;\n//msg.payload=justCueParts.flat(Infinity); \n//msg.sentences=sourceLanguage2; \nmsg.payload=sourceLanguage2;\nreturn msg;","outputs":1,"noerr":0,"x":2404,"y":776,"wires":[["c6e37940.6bd438","9a25d994.e5e7f8"]]},{"id":"59bbce12.d051b","type":"debug","z":"dbbf8510.63c748","name":"xlate sentences","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2688,"y":744,"wires":[]},{"id":"ea035f77.89574","type":"debug","z":"dbbf8510.63c748","name":"just cues","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2676,"y":808,"wires":[]},{"id":"ba66a814.025a78","type":"change","z":"dbbf8510.63c748","name":"","rules":[{"t":"delete","p":"newSentence","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":2334,"y":744,"wires":[["59bbce12.d051b","80114ff.5ab5eb"]]},{"id":"9a25d994.e5e7f8","type":"change","z":"dbbf8510.63c748","name":"","rules":[{"t":"delete","p":"sourceLanguage","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":2344,"y":808,"wires":[["ea035f77.89574"]]},{"id":"47badcd0.abbfb4","type":"function","z":"dbbf8510.63c748","name":"set translate v2","func":"\nvar translate_apiurl = flow.get(\"translate_apiurl\");\nvar translate_basic_auth_key = flow.get(\"translate_basic_auth_key\");\n/*\nPOST /language-translator/api/v3/translate?version=2018-05-01 HTTP/1.1\nHost: gateway.watsonplatform.net\nContent-Type: application/json\n\nAuthorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n{\"text\": [\"Hello, world! \", \"How are you?\"], \"model_id\":\"en-de\"};\n\n\n*/\n//var payloadTest = msg.payload;\n//msg.payload={};\n\n// hard coded version number in api call. could remove and put into var.\nmsg.url = flow.get(\"translate_apiurl\")+\"?version=2018-05-01\";\n//msg.url =\"https://gateway.watsonplatform.net/language-translator/api/v3/translate?version=2018-05-01\"\nmsg.myurl=flow.get(\"translate_apiurl\");\n// to get Basic Authorization key:\n// base_encode \"apikey:\" + your api key. Store in flow vars Use ISO-8859-1 character set \nmsg.headers = {\"Authorization\": \"Basic \" + translate_basic_auth_key,\"content-type\":\"application/json\"};\nmsg.payload={\"text\": msg.payload, \"model_id\":msg.translate_model_id}; // NOTE: This is translations model: https://cloud.ibm.com/docs/services/language-translator?topic=language-translator-translation-models\n//msg.payload={\"text\": msg.payload, \"model_id\":\"en-fr\"}; // NOTE: This is translations model: https://cloud.ibm.com/docs/services/language-translator?topic=language-translator-translation-models\n\n\nreturn msg;","outputs":1,"noerr":0,"x":2304,"y":584,"wires":[["22f9e427.77d46c","1932afff.8d91f"]]},{"id":"a713eaf5.71eef8","type":"function","z":"dbbf8510.63c748","name":"Flatten Array v2","func":"var arrayToFlatten = msg.payload.translations;\n\nvar flattenedArray = [].concat.apply([], arrayToFlatten);\nmsg.payload=flattenedArray\n\n\nreturn msg;","outputs":1,"noerr":0,"x":2304,"y":616,"wires":[["b02b4208.a3869","f5bd1ae.93228e8"]]},{"id":"826996c5.ff3768","type":"function","z":"dbbf8510.63c748","name":"Flatten Array v2","func":"//Flatten Array v2. Switched to concat from mozilla .flat\nvar arrayToFlatten = msg.payload;\nvar flattenedArray = [].concat.apply([], arrayToFlatten);\nmsg.payload=flattenedArray\n\n\nreturn msg;","outputs":1,"noerr":0,"x":2304,"y":680,"wires":[["c994f6.bc553b08","58aff479.46e67c"]]},{"id":"401426cb.9c7c98","type":"function","z":"dbbf8510.63c748","name":"set flow vars","func":"flow.set(\"SMapihost\", \"https://api.video.ibm.com\"); \n\nflow.set(\"client_id\", \"\"); \nflow.set(\"client_secret\", \"\");\nflow.set(\"token_type\", \"bearer\"); //SM token type\n\n\n// translation\nflow.set(\"SM_channel_id\",\"\"); //string channel_id to monitor\nflow.set(\"translate_field\",\"\"); // multi_select\nflow.set(\"status_log_field\",\"\"); // tag list new 0210/2020 used to update status\n\nflow.set(\"translate_apiurl\",\"https://gateway.watsonplatform.net/language-translator/api\");\nflow.set(\"language_source\",\"en-US\");// default source language en-US\nflow.set(\"translate_apikey\",\"\");\nflow.set(\"translate_basic_auth_key\",\"\");\n\n\n// don't change this one unless the version of api changes\n// this just appends the api version to the end of translate API url pulled from Watson Translator Credentials page\nflow.set(\"translate_apiurl\",flow.get(\"translate_apiurl\")+\"/v3/translate\");\n\n\n\n\nreturn msg;","outputs":1,"noerr":0,"x":374,"y":840,"wires":[["e70e9f0d.c1554"]]}]