video.html 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  6. <title></title>
  7. <style>
  8. </style>
  9. </head>
  10. <body>
  11. <div id='app'>
  12. <div class="verify-placeholder">
  13. <div class="verify-placeholder-img"></div>
  14. <p class="verify-placeholder-text">正面平视手机、保证光线充足<br>请勿遮挡面部</p>
  15. </div>
  16. <div class="verify-bottom">
  17. <ul class="verify-process">
  18. <li>
  19. <span class="num">1</span>
  20. <p class="text">人脸放入框内,点击开始录制</p>
  21. </li>
  22. <li>
  23. <span class="num">2</span>
  24. <p class="text">录制倒计时<span class="text-tips">(8s)</span>,点击立即结束</p>
  25. </li>
  26. <li>
  27. <span class="num">3</span>
  28. <p class="text">完成录制,等待验证结果</p>
  29. </li>
  30. </ul>
  31. <button class="verify-btn" @click="getCamera">开始录制</button>
  32. </div>
  33. <div class="btn-submit">
  34. <button class="app-button-warning" size="small" @click="$router.back(-1)">上一步</button>
  35. <button type="primary" size="small" class="btn">下一步</button>
  36. </div>
  37. <!-- 人脸检测-->
  38. <div class="video" v-show="showVideo">
  39. <div class="video-cover"></div>
  40. <video :src="url" ref="videoRef" autoplay playsinline x5-video-player-type="h5"></video>
  41. <!-- 关闭按钮 -->
  42. <button class="video-close" @click="closeVideo">×</button>
  43. <button class="video-save" @click="saveVideo">
  44. {{ isAlreadyRecord ? '结束录制(' + count + 's)' : '开始录制' }}</button>
  45. </div>
  46. <video ref="videob" controls="" name="media" v-show="!showVideo" width="100%" height="400"></video>
  47. </div>
  48. </body>
  49. <script src="vue.min.js"></script>
  50. <script src="https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/jquery.min.js"></script>
  51. <script src="base64.js"></script>
  52. <script src="crypto.js"></script>
  53. <!-- <script src="oss.js"></script> -->
  54. <!-- <script src="video.js"></script> -->
  55. <script>
  56. new Vue({
  57. el: '#app',
  58. data: {
  59. url: '',
  60. showVideo: false,
  61. mediaRecorder: null,
  62. MediaStreamTrack: null,
  63. isAlreadyRecord: false,
  64. count: 8,
  65. countTimer: null,
  66. recordedBlobs: [],
  67. compId: ''
  68. },
  69. beforeDestroy() {
  70. this.MediaStreamTrack && this.MediaStreamTrack.stop()
  71. this.countTimer && clearTimeout(this.countTimer)
  72. },
  73. computed: {},
  74. mounted() {
  75. },
  76. watch: {},
  77. methods: {
  78. getPolicyBase64() {
  79. let date = new Date();
  80. date.setHours(date.getHours() + 87600);
  81. let srcT = date.toISOString();
  82. const policyText = {
  83. "expiration": srcT, //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了
  84. "conditions": [
  85. ["content-length-range", 0, 5 * 1024 * 1024] // 设置上传文件的大小限制,5mb
  86. ]
  87. };
  88. const policyBase64 = Window.base64.encode(JSON.stringify(policyText));
  89. console.log(policyBase64);
  90. return policyBase64;
  91. },
  92. getSignature(policyBase64) {
  93. const accesskey = 'FpClTp4OVrRRtHEfi3lBOWUoLxKieW';
  94. // console.log('video.js')
  95. // console.log(Crypto)
  96. const bytes = Window.Crypto.HMAC(Window.Crypto.SHA1, policyBase64, accesskey, {
  97. asBytes: true
  98. })
  99. const signature = Window.Crypto.util.bytesToBase64(bytes);
  100. // console.log(signature);
  101. return signature;
  102. },
  103. uploadFile(policyBase64) {
  104. var formdata = new FormData()
  105. // const policyBase64 = this.getPolicyBase64();
  106. console.log("policyBase64-----------------------")
  107. console.log(policyBase64)
  108. const signature = this.getSignature(policyBase64); //获取签名
  109. console.log("signatur--------------------------------------e")
  110. console.log(signature)
  111. formdata.append("key", "https://taohaoliang.oss-cn-beijing.aliyuncs.com")
  112. formdata.append("policy", policyBase64)
  113. formdata.append("OSSAccessKeyId", 'LTAI4G9c14PgKvM23WZ9zrpc')
  114. formdata.append("signature", signature)
  115. formdata.append("success_action_status", '200')
  116. $.ajax({
  117. type: "POST",
  118. contentType: "application/json;charset=UTF-8",
  119. url: 'https://taohaoliang.oss-cn-beijing.aliyuncs.com',
  120. success: function(result) {
  121. console.log("result", result);
  122. },
  123. //请求失败,包含具体的错误信息
  124. error: function(e) {
  125. console.log(e);
  126. console.log(e.status);
  127. console.log(e.responseText);
  128. }
  129. });
  130. },
  131. // 调用摄像头 开始录制
  132. getCamera() {
  133. // 注意本例需要在HTTPS协议网站中运行,新版本Chrome中getUserMedia接口在http下不再支持。
  134. let constraints = {
  135. audio: true,
  136. video: {
  137. facingMode: 'user' // 优先调前置摄像头
  138. }
  139. }
  140. console.log('--------------')
  141. console.log(navigator)
  142. // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
  143. if (navigator.mediaDevices === undefined) {
  144. navigator.mediaDevices = {}
  145. }
  146. // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
  147. // 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
  148. if (navigator.mediaDevices.getUserMedia === undefined) {
  149. navigator.mediaDevices.getUserMedia = function(constraints) {
  150. // 首先,如果有getUserMedia的话,就获得它
  151. // var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia
  152. var getUserMedia = navigator.getUserMedia ||
  153. navigator.webkitGetUserMedia ||
  154. navigator.mozGetUserMedia
  155. // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
  156. if (!getUserMedia) {
  157. this.$messageBox.alert('该浏览器不支持getUserMedia,请使用其他浏览器')
  158. return Promise.reject(new Error(
  159. 'getUserMedia is not implemented in this browser'))
  160. }
  161. // 否则,为老的navigator.getUserMedia方法包裹一个Promise
  162. return new Promise(function(resolve, reject) {
  163. getUserMedia.call(navigator, constraints, resolve, reject)
  164. })
  165. }
  166. }
  167. navigator.mediaDevices.getUserMedia(constraints)
  168. .then((stream) => {
  169. this.MediaStreamTrack = typeof stream.stop === 'function' ? stream : stream
  170. .getTracks()[0]
  171. console.log(stream)
  172. console.log(this.MediaStreamTrack)
  173. // 显示录制框
  174. this.showVideo = true
  175. this.isAlreadyRecord = false
  176. let winURL = window.URL || window.webkitURL
  177. if ('srcObject' in this.$refs.videoRef) {
  178. this.$refs.videoRef.srcObject = stream
  179. } else {
  180. this.$refs.videoRef.src = winURL.createObjectURL(stream)
  181. }
  182. console.log(this.$refs.videoRef)
  183. this.$refs.videoRef.onloadedmetadata = e => {
  184. // 播放视频
  185. this.$refs.videoRef.play()
  186. }
  187. let options = {
  188. videoBitsPerSecond: 2500000
  189. }
  190. this.mediaRecorder = new MediaRecorder(stream, options)
  191. })
  192. .catch((err) => {
  193. console.log(err)
  194. this.$messageBox.alert('摄像头开启失败,请检查摄像头是否授权或是否可用!')
  195. })
  196. },
  197. // 关闭活体检测
  198. closeVideo() {
  199. this.recordedBlobs = ''
  200. this.isAlreadyRecord = false
  201. this.MediaStreamTrack && this.MediaStreamTrack.stop()
  202. this.countTimer && clearTimeout(this.countTimer)
  203. this.$router.go(0)
  204. },
  205. // 录制倒计时
  206. countDown() {
  207. let that = this
  208. let sendTime = Math.round(+new Date() / 1000)
  209. return function walk() {
  210. that.countTimer = setTimeout(function() {
  211. that.countTimer && clearTimeout(that.countTimer)
  212. let diff = sendTime + 8 - Math.round(+new Date() / 1000)
  213. if (diff > 0) {
  214. that.count = diff
  215. walk()
  216. } else {
  217. console.log('倒计时结束')
  218. this.showVideo = false
  219. console.log(this.url)
  220. console.log(this.MediaStreamTrack)
  221. }
  222. }, 1000)
  223. }
  224. },
  225. // 保存录制视频
  226. saveVideo() {
  227. if (this.isAlreadyRecord) {
  228. this.countTimer && clearTimeout(this.countTimer)
  229. this.showVideo = false
  230. //当录制的数据可用时
  231. this.mediaRecorder.ondataavailable = (e) => {
  232. if (e.data && e.data.size > 0) {
  233. this.recordedBlobs.push(e.data)
  234. }
  235. }
  236. this.mediaRecorder.stop()
  237. setTimeout(() => {
  238. var blob = new Blob(this.recordedBlobs, {
  239. type: 'video/mp4'
  240. })
  241. // console.log(blob)
  242. this.isAlreadyRecord = false
  243. this.MediaStreamTrack && this.MediaStreamTrack.stop()
  244. var reader = new FileReader();
  245. reader.readAsDataURL(blob, 'utf-8')
  246. reader.onload = () => {
  247. console.log('11111111111111111')
  248. console.log(reader.result); // base64格式
  249. this.$refs.videob.src = reader.result
  250. this.uploadFile(reader.result)
  251. console.log(reader)
  252. }
  253. }, 1000)
  254. } else {
  255. this.count = 8
  256. this.isAlreadyRecord = true
  257. this.mediaRecorder.start(8000)
  258. this.countDown()()
  259. }
  260. },
  261. changeVideo(e) {
  262. let file = this.$refs.videoFile.files
  263. console.log(file)
  264. }
  265. }
  266. })
  267. </script>
  268. </html>