|
@@ -2,12 +2,49 @@
|
|
|
// This starter template is using Vue 3 <script setup> SFCs
|
|
// This starter template is using Vue 3 <script setup> SFCs
|
|
|
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
|
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
|
|
import HelloWorld from './components/HelloWorld.vue';
|
|
import HelloWorld from './components/HelloWorld.vue';
|
|
|
|
|
+import { FFmpeg } from '@ffmpeg/ffmpeg';
|
|
|
import { VideoRecorder } from '@simaq/core';
|
|
import { VideoRecorder } from '@simaq/core';
|
|
|
-import { onMounted } from 'vue';
|
|
|
|
|
|
|
+import { onMounted, ref } from 'vue';
|
|
|
import { Howler, Howl } from 'howler';
|
|
import { Howler, Howl } from 'howler';
|
|
|
|
|
+import { fetchFile, toBlobURL } from '@ffmpeg/util';
|
|
|
|
|
+const ffmpeg = new FFmpeg();
|
|
|
|
|
+
|
|
|
|
|
+const load = async () => {
|
|
|
|
|
+ // const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.2/dist/esm';
|
|
|
|
|
+ const baseMTURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.3/dist/esm';
|
|
|
|
|
+ try {
|
|
|
|
|
+ // debugger
|
|
|
|
|
+ ffmpeg.on('log', ({ message }) => {
|
|
|
|
|
+ console.log(message);
|
|
|
|
|
+ });
|
|
|
|
|
+ // toBlobURL is used to bypass CORS issue, urls with the same
|
|
|
|
|
+ // domain can be used directly.
|
|
|
|
|
+ await ffmpeg.load({
|
|
|
|
|
+ coreURL: await toBlobURL(
|
|
|
|
|
+ `${baseMTURL}/ffmpeg-core.js`,
|
|
|
|
|
+ 'text/javascript',
|
|
|
|
|
+ ),
|
|
|
|
|
+ wasmURL: await toBlobURL(
|
|
|
|
|
+ `${baseMTURL}/ffmpeg-core.wasm`,
|
|
|
|
|
+ 'application/wasm',
|
|
|
|
|
+ ),
|
|
|
|
|
+ workerURL: await toBlobURL(
|
|
|
|
|
+ `${baseMTURL}/ffmpeg-core.worker.js`,
|
|
|
|
|
+ 'text/javascript',
|
|
|
|
|
+ ),
|
|
|
|
|
+ });
|
|
|
|
|
+ console.log('ffmpeg-isLoad');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('ffmpeg-load-error', error);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ load();
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
// import { add } from "lodash-es";
|
|
// import { add } from "lodash-es";
|
|
|
// import { meaningOfLife } from "@simaq/foo";
|
|
// import { meaningOfLife } from "@simaq/foo";
|
|
|
-console.log('howler', Howler, Howl);
|
|
|
|
|
|
|
+// console.log('howler', Howler, Howl);
|
|
|
let sound = new Howl({
|
|
let sound = new Howl({
|
|
|
html5: false,
|
|
html5: false,
|
|
|
src: ['gs-16b-2c-44100hz.wav'],
|
|
src: ['gs-16b-2c-44100hz.wav'],
|
|
@@ -16,11 +53,12 @@ const videoRecorder = new VideoRecorder({
|
|
|
// uploadUrl: '',
|
|
// uploadUrl: '',
|
|
|
resolution: '4k',
|
|
resolution: '4k',
|
|
|
autoDownload: false,
|
|
autoDownload: false,
|
|
|
- platform: 'canvas',
|
|
|
|
|
|
|
+ platform: 'electron',
|
|
|
// disabledAudio: false,
|
|
// disabledAudio: false,
|
|
|
config: {
|
|
config: {
|
|
|
- frameRate: 60,
|
|
|
|
|
- canvasId: '#testCanvas',
|
|
|
|
|
|
|
+ // frameRate: 60,
|
|
|
|
|
+ chromeMediaSourceId:""
|
|
|
|
|
+ // canvasId: '#testCanvas',
|
|
|
},
|
|
},
|
|
|
systemAudio: true,
|
|
systemAudio: true,
|
|
|
debugShowVideo: false,
|
|
debugShowVideo: false,
|
|
@@ -45,10 +83,10 @@ videoRecorder.on('record', (data: Blob) => {
|
|
|
//录屏后片断数据
|
|
//录屏后片断数据
|
|
|
console.log('record', data);
|
|
console.log('record', data);
|
|
|
});
|
|
});
|
|
|
-videoRecorder.on('endRecord', (data) => {
|
|
|
|
|
|
|
+videoRecorder.on('endRecord', async (data) => {
|
|
|
console.log('endRecord', data);
|
|
console.log('endRecord', data);
|
|
|
sound.stop();
|
|
sound.stop();
|
|
|
- handleAutoDownload([data]);
|
|
|
|
|
|
|
+ handleAutoDownload(data);
|
|
|
//结束录屏event
|
|
//结束录屏event
|
|
|
});
|
|
});
|
|
|
videoRecorder.on('cancelRecord', () => {
|
|
videoRecorder.on('cancelRecord', () => {
|
|
@@ -56,21 +94,41 @@ videoRecorder.on('cancelRecord', () => {
|
|
|
//cancel录屏event
|
|
//cancel录屏event
|
|
|
});
|
|
});
|
|
|
const handleAutoDownload = async (chunks: Blob[]) => {
|
|
const handleAutoDownload = async (chunks: Blob[]) => {
|
|
|
- const downloadBlob = new Blob(chunks, {
|
|
|
|
|
- type: 'video/mp4; codecs=h264',
|
|
|
|
|
- });
|
|
|
|
|
- // const downloadBlob = await fixWebmMetaInfo(
|
|
|
|
|
- // new Blob(chunks, { type: 'video/webm; codecs=h264' }),
|
|
|
|
|
- // );
|
|
|
|
|
- const url = URL.createObjectURL(downloadBlob);
|
|
|
|
|
- const a: HTMLAnchorElement = document.createElement('a');
|
|
|
|
|
- document.body.appendChild(a);
|
|
|
|
|
- a.style.display = 'none';
|
|
|
|
|
- a.href = url;
|
|
|
|
|
- const name = new Date().getTime();
|
|
|
|
|
- a.download = `${name}.mp4`;
|
|
|
|
|
- a.click();
|
|
|
|
|
- window.URL.revokeObjectURL(url);
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ console.log('handleAutoDownload');
|
|
|
|
|
+ const downloadBlob = new Blob(chunks, {
|
|
|
|
|
+ type: 'video/webm',
|
|
|
|
|
+ });
|
|
|
|
|
+ const url = URL.createObjectURL(downloadBlob);
|
|
|
|
|
+
|
|
|
|
|
+ await ffmpeg.writeFile('input.webm', await fetchFile(url));
|
|
|
|
|
+
|
|
|
|
|
+ console.log('进入3', await ffmpeg.listDir('/'));
|
|
|
|
|
+ console.log('进入3', await ffmpeg.readFile('input.webm'));
|
|
|
|
|
+ await ffmpeg.exec([
|
|
|
|
|
+ '-i',
|
|
|
|
|
+ 'input.webm',
|
|
|
|
|
+ // '-c:a copy -c:v libx264',
|
|
|
|
|
+ 'output.mp4',
|
|
|
|
|
+ ]);
|
|
|
|
|
+ const data = await ffmpeg.readFile('output.mp4');
|
|
|
|
|
+ console.log('进入成功', data);
|
|
|
|
|
+
|
|
|
|
|
+ const covertURl = URL.createObjectURL(
|
|
|
|
|
+ //@ts-ignore
|
|
|
|
|
+ new Blob([data.buffer], { type: 'video/mp4' }),
|
|
|
|
|
+ );
|
|
|
|
|
+ const a: HTMLAnchorElement = document.createElement('a');
|
|
|
|
|
+ document.body.appendChild(a);
|
|
|
|
|
+ a.style.display = 'none';
|
|
|
|
|
+ a.href = covertURl;
|
|
|
|
|
+ const name = new Date().getTime();
|
|
|
|
|
+ a.download = `${name}.mp4`;
|
|
|
|
|
+ a.click();
|
|
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error(error);
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
// const GoldPlay = (window as any).GoldPlay;
|
|
// const GoldPlay = (window as any).GoldPlay;
|