video.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // miniprogram/pages/video/video.js
  2. const app = getApp()
  3. import { formatTime } from "../../utils/util"
  4. Page({
  5. /**
  6. * 页面变量
  7. */
  8. lastUp: 0,
  9. playIndex: 0,
  10. duration: 0,
  11. lastTime: 0,
  12. allDuration: 0,
  13. touchtVideoStart: 0,
  14. touchtVideoStartTime: 0,
  15. audioTextUrl: "",
  16. progressWidth: 0,
  17. lastProTime: (new Date()) - 251,
  18. operation: {
  19. step: [],
  20. index: 0
  21. },
  22. /**
  23. * 页面的初始数据
  24. */
  25. data: {
  26. stepIndex: 0,
  27. isScroll: false,
  28. maxStepIndex: 0,
  29. allDurationFormat: "00:00:00",
  30. durationFormat: "00:00:00",
  31. textClip: undefined,
  32. playStatus: false,
  33. currentValue: "",
  34. active: "none",
  35. showBg: false,
  36. muted: true,
  37. imgFrame: [],
  38. playerCom: 1,
  39. progress: 0,
  40. music: [],
  41. urlTwo: {
  42. url: "",
  43. i: 0
  44. },
  45. urlOne: {
  46. url: "",
  47. i: 0
  48. },
  49. },
  50. /**
  51. * 生命周期函数--监听页面初次渲染完成
  52. */
  53. onReady: function () {
  54. wx.setStorageSync('music', "");
  55. let allDuration = 0;
  56. let imgFrame = [];
  57. let p = {};
  58. let pageData = getCurrentPages();
  59. let initData = app.globalData.generate[pageData[pageData.length - 1].options.select] || {};
  60. this.player = wx.createVideoContext('myVideo');
  61. this.player2 = wx.createVideoContext('myVideo2');
  62. if (pageData[pageData.length - 1].options.select !== undefined) {
  63. app.globalData.select = [initData];// 查看已经生成
  64. p.muted = false;
  65. }
  66. app.globalData.select.map(v => {
  67. allDuration += v.secDuration * 100;
  68. if (pageData[pageData.length - 1].options.select !== undefined) {
  69. let l = v.clips || []
  70. imgFrame = imgFrame.concat(...l.map(m => {
  71. return m.snaps
  72. }))
  73. } else imgFrame = imgFrame.concat(v.snaps)
  74. })
  75. // 总时长
  76. allDuration = Math.ceil(allDuration / 100);
  77. this.allDuration = allDuration;
  78. p.currentValue = initData.currentValue || "";
  79. p.music = initData.music || [];
  80. p.imgFrame = imgFrame;
  81. p.urlOne = {
  82. url: app.globalData.select[0].video,
  83. i: 0,
  84. };
  85. p.allDurationFormat = this.format(allDuration);
  86. if (app.globalData.select.length >= 2) {
  87. p.urlTwo = {
  88. url: app.globalData.select[1].video,
  89. i: 1,
  90. }
  91. }
  92. this.setData(p);
  93. // 获得屏幕宽
  94. const query = wx.createSelectorQuery();
  95. query.select('.progressLong').boundingClientRect((res) => {
  96. this.progressWidth = res.width;
  97. }).exec();
  98. },
  99. onUnload() {
  100. this.audio && this.audio.destroy();
  101. this.audioText && this.audioText.destroy();
  102. this.pause();
  103. },
  104. /**
  105. * 播放进度更新
  106. */
  107. upProgress: function (e) {
  108. let newTime = new Date();
  109. if (this.data.isScroll || !e.detail.duration || newTime - this.lastProTime < 30) return;
  110. this.lastProTime = newTime - 0;
  111. let list = app.globalData.select || [];
  112. let endIndex = this.playIndex;
  113. let duration = 0;
  114. // 记录当前播放时间占总时长
  115. for (let i = 0; i < endIndex; i++) {
  116. const v = list[i];
  117. duration += v.secDuration;
  118. }
  119. duration += e.detail.currentTime;
  120. this.duration = duration;
  121. this.setData({
  122. durationFormat: this.format(Math.ceil(this.duration)),
  123. progress: duration / this.allDuration * this.progressWidth
  124. })
  125. },
  126. /**
  127. * 切换播放器
  128. */
  129. videoEnd() {
  130. this.player.pause();
  131. this.player2.pause();
  132. let playIndex = this.playIndex + 1 > app.globalData.select.length - 1 ? 0 : this.playIndex + 1;
  133. let newPlay = playIndex % 2 === 0;
  134. let next = {
  135. url: app.globalData.select[playIndex].video,
  136. i: playIndex
  137. }
  138. let nnext = app.globalData.select[playIndex + 1] ? {
  139. url: app.globalData.select[playIndex + 1].video,
  140. i: playIndex + 1
  141. } : undefined
  142. let p = {
  143. playerCom: newPlay
  144. }
  145. if (newPlay) {
  146. // 第一个
  147. p.urlOne != next && (p.urlOne = next);
  148. nnext && (p.urlTwo = nnext);
  149. } else {
  150. // 第二个
  151. p.urlTwo != next && (p.urlTwo = next);
  152. nnext && (p.urlOne = nnext);
  153. }
  154. this.setData(p, () => {
  155. if (this.playIndex + 1 > app.globalData.select.length - 1) {
  156. console.log("片段结束-------->", this.progressWidth)
  157. this.audio && this.audio.pause();
  158. this.audioText && this.audioText.pause();
  159. this.audio && this.audio.seek(0);
  160. this.audioText && this.audioText.seek(0);
  161. this.playIndex = 0;
  162. this.setData({ playStatus: false, progress: this.progressWidth })
  163. } else if (this.data.playStatus) {
  164. this.playIndex++;
  165. if (newPlay) this.player.play();
  166. else this.player2.play();
  167. }
  168. })
  169. },
  170. /**
  171. * 加载中
  172. */
  173. bindwaiting() {
  174. console.log("加载--------->");
  175. },
  176. /**
  177. * 播放中
  178. */
  179. bindplay() {
  180. console.log("播放--------->")
  181. },
  182. /**
  183. * 加载进度
  184. */
  185. bindprogress1(e){
  186. console.log("加载进度1--------->",e.detail)
  187. },
  188. bindprogress2(e){
  189. console.log("加载进度2--------->",e.detail)
  190. },
  191. play() {
  192. let newPlay = this.playIndex % 2 === 0;
  193. if (newPlay) this.player.play();
  194. else this.player2.play();
  195. this.audio && this.audio.play();
  196. this.audioText && this.audioText.play();
  197. this.setData({
  198. playStatus: true
  199. })
  200. },
  201. seek(s) {
  202. let dur = 0;
  203. for (let i = 0; i < app.globalData.select.length; i++) {
  204. const v = app.globalData.select[i];
  205. if (dur + v.secDuration >= s) {
  206. this.playIndex = i;
  207. let sec = s - dur;
  208. let newPlay = i % 2 === 0;
  209. sec < 0.1 && (sec = 0);
  210. if (newPlay) { this.player.seek(sec); this.player2.seek(0); }
  211. else { this.player2.seek(sec); this.player.seek(0); }
  212. this.audio && this.audio.seek(0);
  213. this.audioText && this.audioText.seek(0);
  214. this.upProgress({
  215. detail: {
  216. currentTime: sec,
  217. duration: s
  218. }
  219. })
  220. let one = app.globalData.select[i] || {};
  221. let two = app.globalData.select[i + 1] || app.globalData.select[0] || {};
  222. this.setData({
  223. playerCom: newPlay,
  224. urlOne: newPlay ? {
  225. url: one.video,
  226. i: i,
  227. } : {
  228. url: two.video,
  229. i: i + 1,
  230. },
  231. urlTwo: !newPlay ? {
  232. url: one.video,
  233. i: i,
  234. } : {
  235. url: two.video,
  236. i: i + 1,
  237. },
  238. })
  239. break
  240. }
  241. dur += v.secDuration;
  242. }
  243. },
  244. pause() {
  245. let newPlay = this.playIndex % 2 === 0;
  246. if (newPlay) this.player.pause();
  247. else this.player2.pause();
  248. this.audio && this.audio.pause();
  249. this.audioText && this.audioText.pause();
  250. this.setData({
  251. playStatus: false
  252. })
  253. },
  254. endProgress() {
  255. this.setData({
  256. isScroll: false,
  257. })
  258. },
  259. /**
  260. * 格式化时分秒
  261. * @param {*} s
  262. */
  263. format(s) {
  264. let sco = Math.floor(s % 60);
  265. let min = Math.floor(s / 60);
  266. let hour = Math.floor(min / 60);
  267. let time = hour > 9 ? hour : "0" + hour;
  268. time += min > 9 ? ":" + min : ":0" + min;
  269. time += sco > 9 ? ":" + sco : ":0" + sco;
  270. return time
  271. },
  272. acttouch(e) {
  273. this.pause();
  274. this.setData({
  275. playStatus: false,
  276. isScroll: true
  277. })
  278. this.touchtVideoStart = e.changedTouches[0].pageX;
  279. this.touchtVideoStartTime = this.duration;
  280. },
  281. // 滚动播放进度
  282. moveProgress(e) {
  283. if (!this.data.isScroll) return
  284. let p = this.progressWidth / this.allDuration;
  285. let duration = e.detail.scrollLeft / p;
  286. duration < 0 ? duration = 0 : duration > this.allDuration ? duration = this.allDuration : "";
  287. this.duration = duration;
  288. this.setData({
  289. durationFormat: this.format(Math.ceil(duration)),
  290. })
  291. this.seek(this.duration)
  292. console.log('滑动触发更新播放进度------->', duration);
  293. },
  294. showText() {
  295. this.pause();
  296. this.setData({
  297. active: "text",
  298. showBg: !this.data.showBg,
  299. playStatus: false
  300. })
  301. },
  302. showMusic() {
  303. this.pause();
  304. this.setData({
  305. active: 'music',
  306. showBg: !this.data.showBg,
  307. playStatus: false
  308. })
  309. },
  310. handleMusicChange(e) {
  311. this.setAudio('audio', e.detail.Url);
  312. this.setData({
  313. music: [e.detail],
  314. active: 'none',
  315. showBg: !this.data.showBg
  316. }, () => {
  317. this.seek(0);
  318. if (!e.detail.notClick) this.addStep();
  319. })
  320. },
  321. handleMusicRemove(e) {
  322. this.setAudio('audio');
  323. this.setData({
  324. music: []
  325. }, () => {
  326. this.addStep();
  327. })
  328. },
  329. showBag() {
  330. this.setData({
  331. active: "none",
  332. showBg: !this.data.showBg
  333. })
  334. },
  335. setAudio(type, url) {
  336. this[type] && this[type].destroy();
  337. if (!url) return
  338. this[type] = wx.createInnerAudioContext()
  339. this[type].src = url // src 可以设置 http(s) 的路径,本地文件路径或者代码包文件路径
  340. this[type].autoplay = true
  341. this[type].loop = type === "audio"
  342. this[type].pause();
  343. this[type].seek(0);
  344. },
  345. // 增加/修改文字
  346. handleText(e) {
  347. console.log(e)
  348. this.setAudio('audioText', e.detail.Url.voice.audio);
  349. this.audioTextUrl = e.detail.Url.voice.audio;
  350. this.setData({
  351. active: "none",
  352. currentValue: e.detail.currentValue,
  353. showBg: !this.data.showBg
  354. }, () => {
  355. this.addStep();
  356. this.seek(0);
  357. })
  358. },
  359. share() {
  360. if (!app.globalData.select.length) return wx.showToast({
  361. title: "请选择视频",
  362. icon: "none"
  363. });
  364. wx.showLoading({
  365. title: "视频生成中..."
  366. });
  367. let indexs = app.globalData.select[0].id.split("-");
  368. let oritem = app.globalData.oriList[indexs[0]] ? app.globalData.oriList[indexs[0]] : {};
  369. let item = JSON.parse(JSON.stringify(oritem));
  370. item.type = "video";
  371. item.video = item.result ? item.result.result_video : "";
  372. item.secDuration = item.result ? item.result.duration : "";
  373. item.music = this.data.music;
  374. item.duration = this.format(this.allDuration);
  375. item.update = formatTime(new Date());
  376. !this.data.currentValue && (item.voice = "")
  377. this.data.currentValue && (item.currentValue = this.data.currentValue);
  378. let pageData = getCurrentPages();
  379. let index = pageData[pageData.length - 1].options.select;
  380. item.id = app.globalData.generate.length + '-';
  381. if (index >= 0) {
  382. item.id = index + '-';
  383. app.globalData.generate[index] = item;
  384. } else app.globalData.generate.push(item);
  385. wx.setStorageSync("generated", JSON.stringify(app.globalData.generate));
  386. let T = setTimeout(() => {
  387. clearTimeout(T);
  388. wx.hideLoading({
  389. success() {
  390. // wx.redirectTo({
  391. // url: "/pages/index/index",
  392. // });
  393. wx.navigateBack({
  394. delta: 11
  395. })
  396. }
  397. });
  398. }, Math.random() * 2000);
  399. },
  400. /**
  401. * 添加步骤
  402. */
  403. addStep() {
  404. this.operation.step.splice(this.operation.index, this.operation.step.length);
  405. this.operation.index += 1;
  406. this.operation.step.push({
  407. music: JSON.stringify(this.data.music),
  408. currentValue: this.data.currentValue,
  409. audioTextUrl: this.audioTextUrl,
  410. select: JSON.stringify(app.globalData.select)
  411. })
  412. this.setData({
  413. stepIndex: this.operation.index,
  414. maxStepIndex: this.operation.step.length
  415. })
  416. },
  417. toStep(i) {
  418. let _this = this;
  419. if (i > this.operation.step.length || i === this.operation.index) return wx.showToast({ title: "步骤错误!", icon: "none" });
  420. let item = this.operation.step[i - 1] || {};
  421. let music = JSON.parse(item.music || '[]');
  422. this.operation.index = i;
  423. // 先将原音频销毁
  424. this.setAudio('audio');
  425. this.setAudio('audioText');
  426. music.length && this.setAudio('audio', music[0].Url)
  427. item.audioTextUrl && this.setAudio('audioText', item.audioTextUrl)
  428. this.setData({
  429. stepIndex: i,
  430. music,
  431. currentValue: item.currentValue || "",
  432. maxStepIndex: this.operation.step.length
  433. }, () => {
  434. _this.seek(0);
  435. _this.pause();
  436. })
  437. },
  438. backStep() {
  439. if (this.operation.index <= 0) return;
  440. this.toStep(this.operation.index - 1);
  441. this.setData({
  442. stepIndex: this.operation.index,
  443. })
  444. },
  445. backNext() {
  446. if (this.operation.index + 1 > this.operation.step.length) return;
  447. this.toStep(this.operation.index + 1);
  448. this.setData({
  449. stepIndex: this.operation.index,
  450. })
  451. }
  452. })