utilgsp.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*
  2. Copyright (C) 2016 Borsato Ivano
  3. The JavaScript code in this page is free software: you can
  4. redistribute it and/or modify it under the terms of the GNU
  5. General Public License (GNU GPL) as published by the Free Software
  6. Foundation, either version 3 of the License, or (at your option)
  7. any later version. The code is distributed WITHOUT ANY WARRANTY;
  8. without even the implied warranty of MERCHANTABILITY or FITNESS
  9. FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
  10. */
  11. 'use strict';
  12. import * as Lib from './convenience.js';
  13. import * as Settings from './settings.js';
  14. // CONST GSP - base
  15. const SCREEN =
  16. '_SCREENCAST_RES_ _ENCODER_VIDEO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! _CONTAINER_';
  17. // CONST GSP - base plus sound
  18. const SCREEN_SOUND =
  19. 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! _SCREENCAST_RES_ _ENCODER_VIDEO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. pulsesrc ! audioconvert ! _ENCODER_AUDIO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. _CONTAINER_ name=mux ';
  20. // CONST GSP - base plus webcam
  21. const SCREEN_WEBCAM =
  22. 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! videomixer name=mix _WEBCAM_OPT_ ! videoconvert ! _SCREENCAST_RES_ _ENCODER_VIDEO_ ! mux. v4l2src _WEBCAM_DEV_ ! _WEBCAM_CAP_ ! videoscale ! video/x-raw, width=_WEBCAM_W_, height=_WEBCAM_H_, add-borders=false ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mix. _CONTAINER_ name=mux';
  23. // CONST GSP - base plus sound and webcam stream
  24. const SCREEN_WEBCAM_SOUND =
  25. 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! videomixer name=mix _WEBCAM_OPT_ ! videoconvert ! _SCREENCAST_RES_ _ENCODER_VIDEO_ ! mux. v4l2src _WEBCAM_DEV_ ! _WEBCAM_CAP_ ! videoscale ! video/x-raw, width=_WEBCAM_W_, height=_WEBCAM_H_, add-borders=false ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mix. pulsesrc ! audioconvert ! _ENCODER_AUDIO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. _CONTAINER_ name=mux';
  26. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  27. // CONST CONTAINER - WebM
  28. const webmVP8 = {
  29. fileExt: '.webm',
  30. nameGSP: 'webmmux',
  31. quality: [
  32. {
  33. // quality level 0
  34. fps: 15,
  35. vq:
  36. 'vp8enc min_quantizer=13 max_quantizer=20 cpu-used=5 deadline=1000000 sharpness=2 target-bitrate=10000 threads=%T',
  37. aq: 'vorbisenc',
  38. descr:
  39. 'FPS: 15 \nVideo -> VP8 Encoder:\n-min_quantizer=13\n-max_quantizer=20\n-cpu-used=5\n-deadline=1000000\n-sharpness=2\n-target-bitrate=10000\nAudio -> Vorbis Encoder',
  40. },
  41. {
  42. // quality level 1
  43. fps: 30,
  44. vq:
  45. 'vp8enc min_quantizer=4 max_quantizer=13 cpu-used=2 deadline=500000 sharpness=0 target-bitrate=15000 threads=%T',
  46. aq: 'vorbisenc',
  47. descr:
  48. 'FPS: 30 \nVideo -> VP8 Encoder:\n-min_quantizer=4\n-max_quantizer=13\n-cpu-used=2\n-deadline=500000\n-sharpness=0\n-target-bitrate=15000\nAudio -> Vorbis Encoder',
  49. },
  50. {
  51. // quality level 2
  52. fps: 30,
  53. vq:
  54. 'vp8enc min_quantizer=0 max_quantizer=7 cpu-used=1 deadline=500000 sharpness=0 target-bitrate=25000 threads=%T',
  55. aq: 'vorbisenc',
  56. descr:
  57. 'FPS: 30 \nVideo -> VP8 Encoder:\n-min_quantizer=0\n-max_quantizer=7\n-cpu-used=1\n-deadline=500000\n-sharpness=0\n-target-bitrate=25000\nAudio -> Vorbis Encoder',
  58. },
  59. {
  60. // quality level 3
  61. fps: 60,
  62. vq:
  63. 'vp8enc min_quantizer=0 max_quantizer=0 cpu-used=0 deadline=100000 sharpness=0 target-bitrate=40000 threads=%T',
  64. aq: 'vorbisenc',
  65. descr:
  66. 'FPS: 60 \nVideo -> VP8 Encoder:\n-min_quantizer=0\n-max_quantizer=0\n-cpu-used=0\n-deadline=100000\n-sharpness=0\n-target-bitrate=40000\nAudio -> Vorbis Encoder',
  67. },
  68. ],
  69. };
  70. const webmVP9 = {
  71. fileExt: '.webm',
  72. nameGSP: 'webmmux',
  73. quality: [
  74. {
  75. // quality level 0
  76. fps: 15,
  77. vq:
  78. 'vp9enc min_quantizer=13 max_quantizer=20 cpu-used=5 deadline=1000000 sharpness=2 target-bitrate=10000 threads=%T',
  79. aq: 'vorbisenc',
  80. descr:
  81. 'FPS: 15 \nVideo -> VP9 Encoder:\n-min_quantizer=13\n-max_quantizer=20\n-cpu-used=5\n-deadline=1000000\n-sharpness=2\n-target-bitrate=10000\nAudio -> Vorbis Encoder',
  82. },
  83. {
  84. // quality level 1
  85. fps: 30,
  86. vq:
  87. 'vp9enc min_quantizer=4 max_quantizer=13 cpu-used=2 deadline=500000 sharpness=0 target-bitrate=15000 threads=%T',
  88. aq: 'vorbisenc',
  89. descr:
  90. 'FPS: 30 \nVideo -> VP9 Encoder:\n-min_quantizer=4\n-max_quantizer=13\n-cpu-used=2\n-deadline=500000\n-sharpness=0\n-target-bitrate=15000\nAudio -> Vorbis Encoder',
  91. },
  92. {
  93. // quality level 2
  94. fps: 30,
  95. vq:
  96. 'vp9enc min_quantizer=0 max_quantizer=7 cpu-used=1 deadline=500000 sharpness=0 target-bitrate=25000 threads=%T',
  97. aq: 'vorbisenc',
  98. descr:
  99. 'FPS: 30 \nVideo -> VP9 Encoder:\n-min_quantizer=0\n-max_quantizer=7\n-cpu-used=1\n-deadline=500000\n-sharpness=0\n-target-bitrate=25000\nAudio -> Vorbis Encoder',
  100. },
  101. {
  102. // quality level 3
  103. fps: 60,
  104. vq:
  105. 'vp9enc min_quantizer=0 max_quantizer=0 cpu-used=0 deadline=100000 sharpness=0 target-bitrate=40000 threads=%T',
  106. aq: 'vorbisenc',
  107. descr:
  108. 'FPS: 60 \nVideo -> VP9 Encoder:\n-min_quantizer=0\n-max_quantizer=0\n-cpu-used=0\n-deadline=100000\n-sharpness=0\n-target-bitrate=40000\nAudio -> Vorbis Encoder',
  109. },
  110. ],
  111. };
  112. // CONST CONTAINER - Mp4
  113. const mp4 = {
  114. fileExt: '.mp4',
  115. nameGSP: 'mp4mux',
  116. quality: [
  117. {
  118. // quality level 0
  119. fps: 15,
  120. vq:
  121. 'x264enc psy-tune="none" speed-preset="superfast" subme=1 qp-min=28 qp-max=40 threads=%T',
  122. aq: 'lamemp3enc',
  123. descr:
  124. 'FPS: 15 \nVideo -> x264enc Encoder:\n-psy-tune="none"\n-speed-preset="superfast"\n-subme=1\n-qp-min=28\n-qp-max=40\nAudio -> Mp3 Encoder',
  125. },
  126. {
  127. // quality level 1
  128. fps: 30,
  129. vq:
  130. 'x264enc psy-tune="animation" speed-preset="fast" subme=5 qp-min=18 qp-max=28 threads=%T',
  131. aq: 'lamemp3enc',
  132. descr:
  133. 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="fast"\n-subme=5\n-qp-min=18\n-qp-max=28\nAudio -> Mp3 Encoder',
  134. },
  135. {
  136. // quality level 2
  137. fps: 30,
  138. vq:
  139. 'x264enc psy-tune="animation" speed-preset="medium" subme=8 qp-min=10 qp-max=18 threads=%T',
  140. aq: 'lamemp3enc',
  141. descr:
  142. 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="medium"\n-subme=8\n-qp-min=10\n-qp-max=18\nAudio -> Mp3 Encoder',
  143. },
  144. {
  145. // quality level 3
  146. fps: 60,
  147. vq:
  148. 'x264enc psy-tune="film" speed-preset="slower" subme=10 qp-min=0 qp-max=10 threads=%T',
  149. aq: 'lamemp3enc',
  150. descr:
  151. 'FPS: 60 \nVideo -> x264enc Encoder:\n-psy-tune="film"\n-speed-preset="slower"\n-subme=10\n-qp-min=0\n-qp-max=10\nAudio -> Mp3 Encoder',
  152. },
  153. ],
  154. };
  155. const mp4Aac = {
  156. fileExt: '.mp4',
  157. nameGSP: 'mp4mux',
  158. quality: [
  159. {
  160. // quality level 0
  161. fps: 15,
  162. vq:
  163. 'x264enc psy-tune="none" speed-preset="superfast" subme=1 qp-min=28 qp-max=40 threads=%T',
  164. aq: 'avenc_aac',
  165. descr:
  166. 'FPS: 15 \nVideo -> x264enc Encoder:\n-psy-tune="none"\n-speed-preset="superfast"\n-subme=1\n-qp-min=28\n-qp-max=40\nAudio -> AAC Encoder',
  167. },
  168. {
  169. // quality level 1
  170. fps: 30,
  171. vq:
  172. 'x264enc psy-tune="animation" speed-preset="fast" subme=5 qp-min=18 qp-max=28 threads=%T',
  173. aq: 'avenc_aac',
  174. descr:
  175. 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="fast"\n-subme=5\n-qp-min=18\n-qp-max=28\nAudio -> AAC Encoder',
  176. },
  177. {
  178. // quality level 2
  179. fps: 30,
  180. vq:
  181. 'x264enc psy-tune="animation" speed-preset="medium" subme=8 qp-min=10 qp-max=18 threads=%T',
  182. aq: 'avenc_aac',
  183. descr:
  184. 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="medium"\n-subme=8\n-qp-min=10\n-qp-max=18\nAudio -> AAC Encoder',
  185. },
  186. {
  187. // quality level 3
  188. fps: 60,
  189. vq:
  190. 'x264enc psy-tune="film" speed-preset="slower" subme=10 qp-min=0 qp-max=10 threads=%T',
  191. aq: 'avenc_aac',
  192. descr:
  193. 'FPS: 60 \nVideo -> x264enc Encoder:\n-psy-tune="film"\n-speed-preset="slower"\n-subme=10\n-qp-min=0\n-qp-max=10\nAudio -> AAC Encoder',
  194. },
  195. ],
  196. };
  197. // CONST CONTAINER - Mkv
  198. const mkv = {
  199. fileExt: '.mkv',
  200. nameGSP: 'matroskamux',
  201. quality: [
  202. {
  203. // quality level 0
  204. fps: 15,
  205. vq:
  206. 'x264enc psy-tune="none" speed-preset="superfast" subme=1 qp-min=28 qp-max=40 threads=%T',
  207. aq: 'flacenc',
  208. descr:
  209. 'FPS: 15 \nVideo -> x264enc Encoder:\n-psy-tune="none"\n-speed-preset="superfast"\n-subme=1\n-qp-min=28\n-qp-max=40\nAudio -> Flac Encoder',
  210. },
  211. {
  212. // quality level 1
  213. fps: 30,
  214. vq:
  215. 'x264enc psy-tune="animation" speed-preset="fast" subme=5 qp-min=18 qp-max=28 threads=%T',
  216. aq: 'flacenc',
  217. descr:
  218. 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="fast"\n-subme=5\n-qp-min=18\n-qp-max=28\nAudio -> Flac Encoder',
  219. },
  220. {
  221. // quality level 2
  222. fps: 30,
  223. vq:
  224. 'x264enc psy-tune="animation" speed-preset="medium" subme=8 qp-min=10 qp-max=18 threads=%T',
  225. aq: 'flacenc',
  226. descr:
  227. 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="medium"\n-subme=8\n-qp-min=10\n-qp-max=18\nAudio -> Flac Encoder',
  228. },
  229. {
  230. // quality level 3
  231. fps: 60,
  232. vq:
  233. 'x264enc psy-tune="film" speed-preset="slower" subme=10 qp-min=0 qp-max=10 threads=%T',
  234. aq: 'flacenc',
  235. descr:
  236. 'FPS: 60 \nVideo -> x264enc Encoder:\n-psy-tune="film"\n-speed-preset="slower"\n-subme=10\n-qp-min=0\n-qp-max=10\nAudio -> Flac Encoder',
  237. },
  238. ],
  239. };
  240. // CONST CONTAINER - Ogg
  241. const ogg = {
  242. fileExt: '.ogg',
  243. nameGSP: 'oggmux',
  244. quality: [
  245. {
  246. // quality level 0
  247. fps: 15,
  248. vq:
  249. 'theoraenc speed-level=3 vp3-compatible=true quality=10 bitrate=10000',
  250. aq: 'opusenc',
  251. descr:
  252. 'FPS: 15 \nVideo -> Theora Encoder:\n-speed-level=3\n-vp3-compatible=true\n-quality=10\n-bitrate=10000\nAudio -> Opus Encoder',
  253. },
  254. {
  255. // quality level 1
  256. fps: 30,
  257. vq:
  258. 'theoraenc speed-level=1 vp3-compatible=false quality=30 bitrate=25000',
  259. aq: 'opusenc',
  260. descr:
  261. 'FPS: 30 \nVideo -> Theora Encoder:\n-speed-level=1\n-vp3-compatible=false\n-quality=30\n-bitrate=25000\nAudio -> Opus Encoder',
  262. },
  263. {
  264. // quality level 2
  265. fps: 30,
  266. vq:
  267. 'theoraenc speed-level=0 vp3-compatible=false quality=50 bitrate=50000',
  268. aq: 'opusenc',
  269. descr:
  270. 'FPS: 30 \nVideo -> Theora Encoder:\n-speed-level=0\n-vp3-compatible=false\n-quality=50\n-bitrate=50000\nAudio -> Opus Encoder',
  271. },
  272. {
  273. // quality level 3
  274. fps: 60,
  275. vq:
  276. 'theoraenc speed-level=0 vp3-compatible=false quality=60 bitrate=100000',
  277. aq: 'opusenc',
  278. descr:
  279. 'FPS: 60 \nVideo -> Theora Encoder\n-speed-level=0\n-vp3-compatible=false\n-quality=60\n-bitrate=100000\nAudio -> Opus Encoder',
  280. },
  281. ],
  282. };
  283. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  284. // CONST RESOLUTION
  285. const RESOLUTION = [
  286. // NATIVE SCREENCAST RESOLUTION
  287. '',
  288. // PRESET/CUSTOM SCREENCAST RESOLUTION
  289. 'videoscale ! video/x-raw, width=_RES_WIDTH_, height=_RES_HEIGHT_, add-borders=_RES_KAR_ ! ',
  290. ];
  291. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  292. // VAR ARRAY CONTAINER
  293. // see cbt_FileContainer in *.glade files for the combo box
  294. const CONTAINER = [webmVP8, webmVP9, mp4, mkv, ogg, mp4Aac];
  295. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  296. /**
  297. * Compose GSP
  298. *
  299. * @param {EasyScreenCastSettings} settings the extension's settings
  300. * @param {MixerAudio} mixer the mixer
  301. *
  302. * @returns {string}
  303. */
  304. export function composeGSP(settings, mixer) {
  305. Lib.TalkativeLog('-§-COMPOSE GSP');
  306. let tmpGSP = '';
  307. // retrieve options
  308. let deviceWebcam = settings.getOption('s', Settings.DEVICE_WEBCAM_SETTING_KEY);
  309. let deviceAudio = settings.getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY);
  310. let qualityGSP = settings.getOption('i', Settings.QUALITY_SETTING_KEY);
  311. let qualityWebcam = settings.getOption('s', Settings.QUALITY_WEBCAM_SETTING_KEY);
  312. let resolutionType = settings.getOption('i', Settings.FILE_RESOLUTION_TYPE_SETTING_KEY);
  313. let resolutionKAR = settings.getOption('b', Settings.FILE_RESOLUTION_KAR_SETTING_KEY);
  314. let resolutionHeight = settings.getOption('i', Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY);
  315. let resolutionWidth = settings.getOption('i', Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY);
  316. let container = settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY);
  317. Lib.TalkativeLog(
  318. `-§-get option||devW: ${deviceWebcam}||devA: ${deviceAudio}||Qgsp: ${qualityGSP}||Qwc: ${qualityWebcam}||Res: ${resolutionType}||Cont: ${container}`
  319. );
  320. if (deviceWebcam !== '') {
  321. switch (deviceAudio) {
  322. case 0:
  323. Lib.TalkativeLog('-§- SCREEN-WEBCAM');
  324. tmpGSP = SCREEN_WEBCAM;
  325. // replace WEBCAM_DEVICE/WEBCAM_CAPS
  326. tmpGSP = _replaceWebcam(
  327. tmpGSP,
  328. deviceWebcam,
  329. qualityWebcam,
  330. settings
  331. );
  332. break;
  333. case 1:
  334. Lib.TalkativeLog('-§-SCREEN-WEBCAM-AUDIO(d)');
  335. tmpGSP = SCREEN_WEBCAM_SOUND;
  336. // replace WEBCAM_DEVICE/WEBCAM_CAPS/ENCODER-AUDIO
  337. tmpGSP = _replaceAudio(
  338. _replaceWebcam(tmpGSP, deviceWebcam, qualityWebcam, settings),
  339. true,
  340. container,
  341. qualityGSP,
  342. mixer
  343. );
  344. break;
  345. default:
  346. Lib.TalkativeLog('-§-SCREEN-WEBCAM-AUDIO');
  347. tmpGSP = SCREEN_WEBCAM_SOUND;
  348. // replace WEBCAM_DEVICE/WEBCAM_CAPS/ENCODER-AUDIO/AUDIO_DEVICE
  349. tmpGSP = _replaceAudio(
  350. _replaceWebcam(tmpGSP, deviceWebcam, qualityWebcam, settings),
  351. false,
  352. container,
  353. qualityGSP,
  354. mixer
  355. );
  356. }
  357. } else {
  358. switch (deviceAudio) {
  359. case 0:
  360. Lib.TalkativeLog('-§-SCREEN');
  361. tmpGSP = SCREEN;
  362. break;
  363. case 1:
  364. Lib.TalkativeLog('-§-SCREEN-AUDIO(d)');
  365. tmpGSP = SCREEN_SOUND;
  366. // replace ENCODER-AUDIO
  367. tmpGSP = _replaceAudio(
  368. tmpGSP,
  369. true,
  370. container,
  371. qualityGSP,
  372. mixer
  373. );
  374. break;
  375. default:
  376. Lib.TalkativeLog('-§-SCREEN-AUDIO');
  377. tmpGSP = SCREEN_SOUND;
  378. // replace ENCODER-AUDIO/AUDIO_DEVICE
  379. tmpGSP = _replaceAudio(
  380. tmpGSP,
  381. false,
  382. container,
  383. qualityGSP,
  384. mixer
  385. );
  386. }
  387. }
  388. // compose resolution string
  389. var resolution = _composeResolution(
  390. resolutionType,
  391. resolutionHeight,
  392. resolutionWidth,
  393. resolutionKAR
  394. );
  395. // replace RESOLUTION/ENCODER-VIDEO/CONTAINER
  396. var mapObj = {
  397. _SCREENCAST_RES_: resolution,
  398. _ENCODER_VIDEO_: CONTAINER[container].quality[qualityGSP].vq,
  399. _CONTAINER_: CONTAINER[container].nameGSP,
  400. };
  401. tmpGSP = tmpGSP.replace(
  402. /_SCREENCAST_RES_|_ENCODER_VIDEO_|_CONTAINER_/gi,
  403. match => {
  404. return mapObj[match];
  405. }
  406. );
  407. Lib.TalkativeLog(`-§-final GSP :${tmpGSP}`);
  408. return tmpGSP;
  409. }
  410. /**
  411. * replace audio
  412. *
  413. * @param {string} gspRA input pipeline to be modified
  414. * @param {boolean} defaultAudio whether to use the default audio device
  415. * @param {int} ConTMP selected output container. Used to determine correct audio encoder
  416. * @param {int} QGSPtmp quality setting
  417. * @param {MixerAudio} mixer audio mixer
  418. * @returns {string} pipeline with audio
  419. */
  420. function _replaceAudio(gspRA, defaultAudio, ConTMP, QGSPtmp, mixer) {
  421. Lib.TalkativeLog(`-§-replace audio default->${defaultAudio}`);
  422. // replace device/encoder
  423. var aq = CONTAINER[ConTMP].quality[QGSPtmp].aq;
  424. Lib.TalkativeLog(`-§-pipeline pre-audio:${gspRA} aq:${aq}`);
  425. var audioPipeline;
  426. if (defaultAudio) {
  427. Lib.TalkativeLog('-§-default audio source');
  428. audioPipeline = gspRA.replace(/_ENCODER_AUDIO_/gi, aq);
  429. } else {
  430. var audiosource = mixer.getAudioSource();
  431. if (audiosource === undefined) {
  432. Lib.TalkativeLog('-§-failure combination of array audio sources');
  433. audioPipeline = gspRA.replace(/_ENCODER_AUDIO_/gi, aq);
  434. } else {
  435. Lib.TalkativeLog('-§-correct audio source assignment');
  436. if (audiosource.indexOf('output') !== -1)
  437. audiosource += '.monitor';
  438. var reDev = `pulsesrc device="${audiosource}"`;
  439. var mapObj = {
  440. pulsesrc: reDev,
  441. _ENCODER_AUDIO_: aq,
  442. };
  443. audioPipeline = gspRA.replace(
  444. /pulsesrc|_ENCODER_AUDIO_/gi,
  445. match => {
  446. return mapObj[match];
  447. }
  448. );
  449. }
  450. }
  451. Lib.TalkativeLog(`-§-pipeline post-audio:${audioPipeline}`);
  452. return audioPipeline;
  453. }
  454. /**
  455. * replace webcam
  456. *
  457. * @param {string} gspRW input pipeline to be modified
  458. * @param {string} device webcam device file (e.g. /dev/video0)
  459. * @param {string} caps quality options
  460. * @param {EasyScreenCastSettings} settings the extension's settings
  461. * @returns {string} pipeline with webcam settings
  462. */
  463. function _replaceWebcam(gspRW, device, caps, settings) {
  464. Lib.TalkativeLog(`-§-replace webcam -> ${device} caps: ${caps}`);
  465. // replace device/caps
  466. var reDev = `device=${device}`;
  467. var reWCopt = _composeWebCamOption(settings);
  468. var [reWCwidth, reWCheight] = _getWebCamDimension(settings);
  469. Lib.TalkativeLog(`-§-pipeline pre-webcam:${gspRW}`);
  470. var mapObj = {
  471. _WEBCAM_DEV_: reDev,
  472. _WEBCAM_CAP_: caps,
  473. _WEBCAM_OPT_: reWCopt,
  474. _WEBCAM_W_: reWCwidth,
  475. _WEBCAM_H_: reWCheight,
  476. };
  477. var webcamPipeline = gspRW.replace(
  478. /_WEBCAM_DEV_|_WEBCAM_CAP_|_WEBCAM_OPT_|_WEBCAM_W_|_WEBCAM_H_/gi,
  479. match => {
  480. return mapObj[match];
  481. }
  482. );
  483. Lib.TalkativeLog(`-§-pipeline post-webcam:${webcamPipeline}`);
  484. return webcamPipeline;
  485. }
  486. /**
  487. * replace resolution
  488. *
  489. * @param {int} tmpRes resolution type: native/custom
  490. * @param {int} h custom height
  491. * @param {int} w custom width
  492. * @param {boolean} kar whether to keep aspect ratio
  493. * @returns {string} pipeline part for scaling resolution
  494. */
  495. function _composeResolution(tmpRes, h, w, kar) {
  496. Lib.TalkativeLog(`-§-resolution option: ${tmpRes}`);
  497. var strRes = RESOLUTION[0];
  498. var mapObj = {};
  499. switch (tmpRes) {
  500. case -1:
  501. break;
  502. case 999:
  503. mapObj = {
  504. _RES_KAR_: kar ? 'true' : 'false',
  505. _RES_HEIGHT_: h,
  506. _RES_WIDTH_: w,
  507. };
  508. strRes = RESOLUTION[1].replace(
  509. /_RES_KAR_|_RES_HEIGHT_|_RES_WIDTH_/gi,
  510. match => {
  511. return mapObj[match];
  512. }
  513. );
  514. break;
  515. default:
  516. mapObj = {
  517. _RES_KAR_: 'true',
  518. _RES_HEIGHT_: h,
  519. _RES_WIDTH_: w,
  520. };
  521. strRes = RESOLUTION[1].replace(
  522. /_RES_KAR_|_RES_WIDTH_|_RES_HEIGHT_/gi,
  523. match => {
  524. return mapObj[match];
  525. }
  526. );
  527. }
  528. Lib.TalkativeLog(`-§-compose resolution: ${strRes}`);
  529. return strRes;
  530. }
  531. /**
  532. * compose option webcam position
  533. *
  534. * @param {EasyScreenCastSettings} settings the extension's settings
  535. *
  536. * @returns {string}
  537. */
  538. function _composeWebCamOption(settings) {
  539. Lib.TalkativeLog('-§-compose webcam option');
  540. // retrieve option webcam
  541. var webcamAlpha = settings.getOption('d', Settings.ALPHA_CHANNEL_WEBCAM_SETTING_KEY);
  542. var webcamMarginX = settings.getOption('i', Settings.MARGIN_X_WEBCAM_SETTING_KEY);
  543. var webcamMarginY = settings.getOption('i', Settings.MARGIN_Y_WEBCAM_SETTING_KEY);
  544. var webcamCornerPosition = settings.getOption('i', Settings.CORNER_POSITION_WEBCAM_SETTING_KEY);
  545. var [webcamWidth, webcamHeight, screenWidth, screenHeight] = _getWebCamDimension(settings);
  546. var posX = 0;
  547. var posY = 0;
  548. Lib.TalkativeLog(
  549. `-§-alpha=${webcamAlpha} |marX=${webcamMarginX} |marY=${webcamMarginY} |corner=${webcamCornerPosition}`
  550. );
  551. // corner top-left
  552. posX = webcamMarginX;
  553. posY = webcamMarginY;
  554. switch (webcamCornerPosition) {
  555. case 0:
  556. // corner bottom-right
  557. posX = Math.floor(screenWidth - (webcamWidth + webcamMarginX));
  558. posY = Math.floor(screenHeight - (webcamHeight + webcamMarginY));
  559. break;
  560. case 1:
  561. // corner bottom-left
  562. posX = webcamMarginX;
  563. posY = Math.floor(screenHeight - (webcamHeight + webcamMarginY));
  564. break;
  565. case 2:
  566. // corner top-right
  567. posX = Math.floor(screenWidth - (webcamWidth + webcamMarginX));
  568. posY = webcamMarginY;
  569. break;
  570. default:
  571. }
  572. // check valid position
  573. if ((posX < 0 || posX > screenWidth) && (posY < 0 || posY > screenHeight)) {
  574. Lib.TalkativeLog('-§-NOT valid position');
  575. posX = 0;
  576. posY = 0;
  577. }
  578. var tmpWCopt =
  579. `sink_0::alpha=1 sink_1::alpha=${
  580. webcamAlpha
  581. } sink_1::xpos=${
  582. posX
  583. } sink_1::ypos=${
  584. posY
  585. } `;
  586. Lib.TalkativeLog(`-§-posX=${posX} |posY=${posY}`);
  587. Lib.TalkativeLog(`-§-webcam option=${tmpWCopt}`);
  588. return tmpWCopt;
  589. }
  590. /**
  591. * retrieve dimension webcam
  592. *
  593. * @param {EasyScreenCastSettings} settings the extension's settings
  594. *
  595. * @returns {*[]} array with webcam width,height,screen-width,screen-height
  596. */
  597. function _getWebCamDimension(settings) {
  598. Lib.TalkativeLog('-§-get webcam dimension');
  599. var webcamWidth = settings.getOption('i', Settings.WIDTH_WEBCAM_SETTING_KEY);
  600. var webcamHeight = settings.getOption('i', Settings.HEIGHT_WEBCAM_SETTING_KEY);
  601. var webcamUnit = settings.getOption('i', Settings.TYPE_UNIT_WEBCAM_SETTING_KEY);
  602. var screenWidth = settings.getOption('i', Settings.WIDTH_SETTING_KEY);
  603. var screenHeight = settings.getOption('i', Settings.HEIGHT_SETTING_KEY);
  604. if (settings.getOption('i', Settings.AREA_SCREEN_SETTING_KEY) === 0) {
  605. screenWidth = global.screen_width;
  606. screenHeight = global.screen_height;
  607. }
  608. Lib.TalkativeLog(
  609. `-§-WC w=${webcamWidth} WC h=${webcamHeight} WCtype=${webcamUnit} screen W=${screenWidth} screen H=${screenHeight}`
  610. );
  611. if (webcamUnit === 0) {
  612. webcamWidth = Math.floor((screenWidth * webcamWidth) / 100);
  613. webcamHeight = Math.floor((screenHeight * webcamHeight) / 100);
  614. }
  615. Lib.TalkativeLog(`-§-after percentage WCw=${webcamWidth} WCh=${webcamHeight}`);
  616. return [webcamWidth, webcamHeight, screenWidth, screenHeight];
  617. }
  618. /**
  619. * get description
  620. *
  621. * @param {int} quality selected quality
  622. * @param {int} container selected container format
  623. * @returns {string}
  624. */
  625. export function getDescr(quality, container) {
  626. Lib.TalkativeLog(`-§-get description Q-> ${quality} C-> ${container}`);
  627. return CONTAINER[container].quality[quality].descr;
  628. }
  629. /**
  630. * get fps
  631. *
  632. * @param {int} quality selected quality
  633. * @param {int} container selected container format
  634. * @returns {number}
  635. */
  636. export function getFps(quality, container) {
  637. Lib.TalkativeLog(`-§-get fps Q-> ${quality} C-> ${container}`);
  638. return CONTAINER[container].quality[quality].fps;
  639. }
  640. /**
  641. * get file extension
  642. *
  643. * @param {int} container selected container format
  644. * @returns {string}
  645. */
  646. export function getFileExtension(container) {
  647. Lib.TalkativeLog(`-§-get file extension C-> ${container}`);
  648. return CONTAINER[container].fileExt;
  649. }