mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2024-11-23 23:21:02 +01:00
feat: 📸 Enhanced recording
This commit is contained in:
parent
9555f58df5
commit
7f10161ad7
91
.vscode/settings.json
vendored
91
.vscode/settings.json
vendored
@ -1,15 +1,67 @@
|
||||
{
|
||||
"eslint.codeAction.showDocumentation": {
|
||||
"enable": true
|
||||
},
|
||||
"eslint.format.enable": true,
|
||||
"prettier.enable": false,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"eslint.format.enable": true,
|
||||
"eslint.codeAction.showDocumentation": {
|
||||
"enable": true
|
||||
},
|
||||
"eslint.rules.customizations": [
|
||||
{
|
||||
"rule": "style/*",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "format/*",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*-indent",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*-spacing",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*-spaces",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*-order",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*-dangle",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*-newline",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*quotes",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
},
|
||||
{
|
||||
"rule": "*semi",
|
||||
"severity": "off",
|
||||
"fixable": true
|
||||
}
|
||||
],
|
||||
"eslint.validate": [
|
||||
// "jsonc",
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
@ -18,19 +70,25 @@
|
||||
"html",
|
||||
"markdown",
|
||||
"json",
|
||||
"yaml"
|
||||
"jsonc",
|
||||
"yaml",
|
||||
"toml",
|
||||
"xml",
|
||||
"gql",
|
||||
"graphql",
|
||||
"astro",
|
||||
"svelte",
|
||||
"css",
|
||||
"less",
|
||||
"scss",
|
||||
"pcss",
|
||||
"postcss"
|
||||
],
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"i18n-ally.localesPaths": ["src/locales/index.js", "src/locales/languages"],
|
||||
"i18n-ally.sourceLanguage": "zh-CN",
|
||||
"i18n-ally.localesPaths": [
|
||||
"src/locales/index.js",
|
||||
"src/locales/languages"
|
||||
],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.extract.ignored": [
|
||||
"Switch",
|
||||
@ -52,5 +110,4 @@
|
||||
"cSpell.words": [
|
||||
"bhsn"
|
||||
],
|
||||
"common-intellisense.ui": []
|
||||
}
|
11
README-CN.md
11
README-CN.md
@ -84,15 +84,18 @@ Windows 及 Linux 端内部集成了 Gnirehtet, 用于提供 PC 到安卓设
|
||||
|
||||
- 镜像
|
||||
- 录制
|
||||
- OTG
|
||||
- 摄像
|
||||
- 录制相机
|
||||
- 录制音频
|
||||
- 相机
|
||||
- 灵活启动
|
||||
- OTG
|
||||
|
||||
### 设备交互栏
|
||||
|
||||
- 切换键
|
||||
- 主屏幕
|
||||
- 返回键
|
||||
- 关闭屏幕(实验性)
|
||||
- 通知栏
|
||||
- 电源键
|
||||
- 旋转屏幕
|
||||
@ -312,6 +315,10 @@ Windows 及 Linux 端内部集成了 Gnirehtet, 用于提供 PC 到安卓设
|
||||
|
||||
你需要自定义 `scrcpy` 以及 `adb` 的文件路径(确保具有可执行权限),如果用到反向供网则同样需要以同样方法配置 `gnirehtet`。
|
||||
|
||||
### Could not execute "adb start-server"
|
||||
|
||||
这可能是因为安装路径中包含中文或特殊字符导致的,请尝试更改安装路径。
|
||||
|
||||
## 获得帮助
|
||||
|
||||
> 因为是开源项目 全靠爱发电 所以支持有限 更新节奏不固定
|
||||
|
11
README-RU.md
11
README-RU.md
@ -82,15 +82,18 @@ Gnirehtet встроен в приложения для Windows и Linux, что
|
||||
|
||||
- Зеркалирование
|
||||
- Запись
|
||||
- OTG
|
||||
- Запись с камеры
|
||||
- Запись аудио
|
||||
- Камера
|
||||
- Пользовательский
|
||||
- Гибкий запуск
|
||||
- OTG
|
||||
|
||||
### Панель взаимодействия с устройством
|
||||
|
||||
- Переключатель
|
||||
- Домой
|
||||
- Назад
|
||||
- Выключение экрана (экспериментально)
|
||||
- Уведомление
|
||||
- Питание
|
||||
- Поворот
|
||||
@ -311,6 +314,10 @@ Gnirehtet встроен в приложения для Windows и Linux, что
|
||||
|
||||
Вам нужно настроить пользовательские пути к файлам для `scrcpy` и `adb` (убедившись, что у них есть разрешения на выполнение). Если вы используете обратный тетеринг, аналогично настройте `gnirehtet`.
|
||||
|
||||
### Could not execute "adb start-server"
|
||||
|
||||
Это может быть вызвано наличием китайских или специальных символов в пути установки. Попробуйте изменить путь установки.
|
||||
|
||||
## Получение помощи
|
||||
|
||||
> Поскольку это проект с открытым исходным кодом, полностью поддерживаемый пожертвованиями, поддержка ограничена, и обновления могут не выходить по фиксированному расписанию.
|
||||
|
@ -82,15 +82,18 @@ Refer to [scrcpy/doc/shortcuts](https://github.com/Genymobile/scrcpy/blob/master
|
||||
|
||||
- Mirror
|
||||
- Recording
|
||||
- OTG
|
||||
- Recording Camera
|
||||
- Recording Audio
|
||||
- Camera
|
||||
- Custom
|
||||
- OTG
|
||||
|
||||
### Device Interaction Bar
|
||||
|
||||
- Switch
|
||||
- Home
|
||||
- Back
|
||||
- Turn off screen (experimental)
|
||||
- Notification
|
||||
- Power
|
||||
- Rotation
|
||||
@ -311,6 +314,10 @@ Please try `disabling audio forwarding` feature through the `preferences setting
|
||||
|
||||
You need to customize the file paths for `scrcpy` and `adb` (ensuring they have executable permissions). If using reverse tethering, configure `gnirehtet` similarly.
|
||||
|
||||
### Could not execute "adb start-server"
|
||||
|
||||
This might be due to Chinese or special characters in the installation path. Please try changing the installation path.
|
||||
|
||||
## Getting Help
|
||||
|
||||
> As this is an open source project run entirely by donations, support is limited and updates may not be on a fixed schedule.
|
||||
|
@ -63,7 +63,6 @@ import { i18n } from '$/locales/index.js'
|
||||
import localeModel from '$/plugins/element-plus/locale.js'
|
||||
|
||||
import { useDeviceStore, useThemeStore } from '$/store/index.js'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const themeStore = useThemeStore()
|
||||
const deviceStore = useDeviceStore()
|
||||
|
@ -10,7 +10,6 @@ export function initControlWindow(mainWindow) {
|
||||
|
||||
const controlWindow = new BrowserWindow({
|
||||
icon: getLogoPath(),
|
||||
parent: mainWindow,
|
||||
width: 700,
|
||||
minWidth: 700,
|
||||
height: 28,
|
||||
|
16
package.json
16
package.json
@ -27,7 +27,7 @@
|
||||
"vue": "3.4.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "3.3.2",
|
||||
"@antfu/eslint-config": "3.8.0",
|
||||
"@devicefarmer/adbkit": "3.2.6",
|
||||
"@electron-toolkit/preload": "3.0.1",
|
||||
"@electron-toolkit/utils": "3.0.0",
|
||||
@ -39,15 +39,15 @@
|
||||
"@vitejs/plugin-vue": "5.0.4",
|
||||
"@vueuse/core": "10.9.0",
|
||||
"dayjs": "1.11.11",
|
||||
"electron": "29.1.1",
|
||||
"electron-builder": "24.13.3",
|
||||
"electron": "33.0.2",
|
||||
"electron-builder": "25.1.8",
|
||||
"electron-context-menu": "4.0.4",
|
||||
"electron-find-in-page": "1.0.8",
|
||||
"electron-log": "5.2.0",
|
||||
"electron-store": "9.0.0",
|
||||
"electron-updater": "6.1.8",
|
||||
"electron-updater": "6.3.9",
|
||||
"element-plus": "2.8.2",
|
||||
"eslint": "9.10.0",
|
||||
"eslint": "9.13.0",
|
||||
"fix-path": "4.0.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"husky": "9.0.11",
|
||||
@ -59,11 +59,11 @@
|
||||
"rimraf": "^6.0.1",
|
||||
"simple-git": "^3.27.0",
|
||||
"unocss": "0.62.3",
|
||||
"unplugin-auto-import": "0.18.2",
|
||||
"unplugin-auto-import": "0.18.3",
|
||||
"unplugin-vue-components": "0.27.4",
|
||||
"vite": "5.1.5",
|
||||
"vite-plugin-electron": "0.28.7",
|
||||
"vite-plugin-electron-renderer": "0.14.5",
|
||||
"vite-plugin-electron": "0.28.8",
|
||||
"vite-plugin-electron-renderer": "0.14.6",
|
||||
"vite-svg-loader": "5.1.0",
|
||||
"vue-command": "35.2.1",
|
||||
"vue-i18n": "9.13.1",
|
||||
|
@ -6,6 +6,7 @@
|
||||
import { sleep } from '$/utils'
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
row: {
|
||||
type: Object,
|
||||
|
@ -14,6 +14,7 @@ export default {
|
||||
components: {
|
||||
DeployDialog,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
row: {
|
||||
type: Object,
|
||||
|
@ -6,6 +6,7 @@
|
||||
import { sleep } from '$/utils'
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
row: {
|
||||
type: Object,
|
||||
|
@ -6,8 +6,31 @@
|
||||
import { sleep } from '$/utils'
|
||||
import { openFloatControl } from '$/utils/device/index.js'
|
||||
|
||||
const recordModel = {
|
||||
default: {
|
||||
excludes: '',
|
||||
command: '',
|
||||
extname: config => config['--record-format'] || 'mp4',
|
||||
},
|
||||
audio: {
|
||||
excludes: ['--video-source', '--no-audio', '--mouse'],
|
||||
commands: ['--no-video', '--mouse=disabled'],
|
||||
extname: config => config['--audio-record-format'] || 'opus',
|
||||
},
|
||||
camera: {
|
||||
excludes: ['--video-source'],
|
||||
commands: ['--video-source=camera'],
|
||||
extname: config => config['--record-format'] || 'mp4',
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
recordType: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
@ -22,6 +45,11 @@ export default {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeModel() {
|
||||
return recordModel[this.recordType]
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async handleClick() {
|
||||
const row = this.row
|
||||
@ -32,25 +60,36 @@ export default {
|
||||
|
||||
const savePath = this.getRecordPath(row)
|
||||
|
||||
const args = this.$store.preference.scrcpyParameter(row.id, {
|
||||
isRecord: true,
|
||||
excludes: ['--otg', '--mouse=aoa', '--keyboard=aoa', '--show-touches'],
|
||||
let args = this.$store.preference.scrcpyParameter(row.id, {
|
||||
isRecord: ['default', 'audio'].includes(this.recordType),
|
||||
isCamera: ['camera'].includes(this.recordType),
|
||||
excludes: [
|
||||
'--otg',
|
||||
'--mouse=aoa',
|
||||
'--keyboard=aoa',
|
||||
'--show-touches',
|
||||
...this.activeModel.excludes,
|
||||
],
|
||||
})
|
||||
|
||||
args += ` ${this.activeModel.commands.join(' ')}`
|
||||
|
||||
console.log('args', args)
|
||||
|
||||
try {
|
||||
const recording = this.$scrcpy.record(row.id, {
|
||||
title: this.$store.device.getLabel(row, 'recording'),
|
||||
savePath,
|
||||
args,
|
||||
stdout: this.onStdout,
|
||||
stderr: this.onStderr,
|
||||
})
|
||||
|
||||
await sleep(1 * 1000)
|
||||
|
||||
this.loading = false
|
||||
|
||||
openFloatControl(toRaw(this.row))
|
||||
if (['default'].includes(this.$props.type)) {
|
||||
openFloatControl(toRaw(this.row))
|
||||
}
|
||||
|
||||
await recording
|
||||
|
||||
@ -65,20 +104,21 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
onStdout() {},
|
||||
onStderr() {},
|
||||
getRecordPath(row) {
|
||||
const config = this.$store.preference.getData(row.id)
|
||||
const basePath = config.savePath
|
||||
const extension = config['--record-format'] || 'mp4'
|
||||
const deviceConfig = this.$store.preference.getData(this.row.id)
|
||||
|
||||
const savePath = deviceConfig.savePath
|
||||
|
||||
const extension = this.activeModel.extname(deviceConfig)
|
||||
|
||||
const fileName = this.$store.device.getLabel(
|
||||
row,
|
||||
({ time }) => `record-${time}.${extension}`,
|
||||
)
|
||||
|
||||
const joinValue = this.$path.join(basePath, fileName)
|
||||
const value = this.$path.normalize(joinValue)
|
||||
const filePath = this.$path.join(savePath, fileName)
|
||||
|
||||
const value = this.$path.normalize(filePath)
|
||||
|
||||
return value
|
||||
},
|
||||
|
@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<slot :loading="loading" :trigger="handleClick" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { sleep } from '$/utils'
|
||||
import { openFloatControl } from '$/utils/device/index.js'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
toggleRowExpansion: {
|
||||
type: Function,
|
||||
default: () => () => false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async handleClick() {
|
||||
const row = this.row
|
||||
|
||||
this.loading = true
|
||||
|
||||
this.toggleRowExpansion(row, true)
|
||||
|
||||
const savePath = this.getRecordPath(row)
|
||||
|
||||
let args = this.$store.preference.scrcpyParameter(row.id, {
|
||||
isRecord: true,
|
||||
excludes: ['--otg', '--mouse=aoa', '--keyboard=aoa', '--video-source', '--show-touches'],
|
||||
})
|
||||
|
||||
args += ' --video-source=camera'
|
||||
|
||||
try {
|
||||
const recording = this.$scrcpy.record(row.id, {
|
||||
title: this.$store.device.getLabel(row, 'recording'),
|
||||
savePath,
|
||||
args,
|
||||
stdout: this.onStdout,
|
||||
stderr: this.onStderr,
|
||||
})
|
||||
|
||||
await sleep(1 * 1000)
|
||||
|
||||
this.loading = false
|
||||
|
||||
openFloatControl(toRaw(this.row))
|
||||
|
||||
await recording
|
||||
|
||||
await this.handleSuccess(savePath)
|
||||
}
|
||||
catch (error) {
|
||||
console.error('record.args', args)
|
||||
console.error('record.error', error)
|
||||
|
||||
if (error.message) {
|
||||
this.$message.warning(error.message)
|
||||
}
|
||||
}
|
||||
},
|
||||
onStdout() {},
|
||||
onStderr() {},
|
||||
getRecordPath(row) {
|
||||
const config = this.$store.preference.getData(row.id)
|
||||
const basePath = config.savePath
|
||||
const extension = config['--record-format'] || 'mp4'
|
||||
|
||||
const fileName = this.$store.device.getLabel(
|
||||
row,
|
||||
({ time }) => `record-${time}.${extension}`,
|
||||
)
|
||||
|
||||
const joinValue = this.$path.join(basePath, fileName)
|
||||
const value = this.$path.normalize(joinValue)
|
||||
|
||||
return value
|
||||
},
|
||||
async handleSuccess(savePath) {
|
||||
return this.$message.success(
|
||||
`${this.$t('device.record.success.title')}: ${savePath}`,
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
@ -17,6 +17,7 @@
|
||||
:key="index"
|
||||
v-bind="{
|
||||
...$props,
|
||||
...(item.props || {}),
|
||||
}"
|
||||
v-slot="{ loading, trigger }"
|
||||
>
|
||||
@ -40,7 +41,6 @@
|
||||
<script>
|
||||
import Record from './components/Record/index.vue'
|
||||
import Camera from './components/Camera/index.vue'
|
||||
import RecordCamera from './components/RecordCamera/index.vue'
|
||||
import Otg from './components/Otg/index.vue'
|
||||
import Custom from './components/Custom/index.vue'
|
||||
|
||||
@ -48,7 +48,6 @@ export default {
|
||||
components: {
|
||||
Record,
|
||||
Camera,
|
||||
RecordCamera,
|
||||
Otg,
|
||||
Custom,
|
||||
},
|
||||
@ -66,12 +65,22 @@ export default {
|
||||
component: 'Record',
|
||||
},
|
||||
{
|
||||
label: 'device.actions.more.camera.name',
|
||||
component: 'Camera',
|
||||
label: 'device.actions.more.recordCamera.name',
|
||||
component: 'Record',
|
||||
props: {
|
||||
recordType: 'camera',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'device.actions.more.recordCamera.name',
|
||||
component: 'RecordCamera',
|
||||
label: 'device.actions.more.recordAudio.name',
|
||||
component: 'Record',
|
||||
props: {
|
||||
recordType: 'audio',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'device.actions.more.camera.name',
|
||||
component: 'Camera',
|
||||
},
|
||||
{
|
||||
label: 'device.actions.more.otg.name',
|
||||
|
@ -253,21 +253,21 @@ export default {
|
||||
await this.$confirm(
|
||||
`<div class="pt-4 pl-4">
|
||||
<div class="text-sm text-red-500 pb-4">${this.$t(
|
||||
'device.wireless.connect.error.detail',
|
||||
)}:${message}</div>
|
||||
'device.wireless.connect.error.detail',
|
||||
)}:${message}</div>
|
||||
<div>${this.$t('device.wireless.connect.error.reasons[0]')}:</div>
|
||||
<div>1. ${this.$t(
|
||||
'device.wireless.connect.error.reasons[1]',
|
||||
)} </div>
|
||||
'device.wireless.connect.error.reasons[1]',
|
||||
)} </div>
|
||||
<div>2. ${this.$t(
|
||||
'device.wireless.connect.error.reasons[2]',
|
||||
)} </div>
|
||||
'device.wireless.connect.error.reasons[2]',
|
||||
)} </div>
|
||||
<div>3. ${this.$t(
|
||||
'device.wireless.connect.error.reasons[3]',
|
||||
)} </div>
|
||||
'device.wireless.connect.error.reasons[3]',
|
||||
)} </div>
|
||||
<div>4. ${this.$t(
|
||||
'device.wireless.connect.error.reasons[4]',
|
||||
)} </div>
|
||||
'device.wireless.connect.error.reasons[4]',
|
||||
)} </div>
|
||||
</div>`,
|
||||
this.$t('device.wireless.connect.error.title'),
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-bind="{ ...(data.props || {}) }"
|
||||
v-bind="{ clearable: true, ...(data.props || {}) }"
|
||||
v-model="selectValue"
|
||||
class="!w-full"
|
||||
>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-bind="{
|
||||
clearable: true,
|
||||
...(data.props || {}),
|
||||
}"
|
||||
v-model="selectValue"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-bind="{ ...(data.props || {}) }"
|
||||
v-bind="{ clearable: true, ...(data.props || {}) }"
|
||||
v-model="selectValue"
|
||||
class="!w-full"
|
||||
>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-form ref="elForm" :model="preferenceData" label-width="225px" class="">
|
||||
<el-form ref="elForm" :model="preferenceData" label-width="250px" class="">
|
||||
<el-collapse
|
||||
v-model="collapseValue"
|
||||
v-bind="{
|
||||
@ -31,61 +31,52 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="pt-4">
|
||||
<el-form
|
||||
ref="elForm"
|
||||
:model="preferenceData"
|
||||
label-width="250px"
|
||||
class="pr-8 pt-4"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col
|
||||
v-for="(item_1, name_1) of subModel(item)"
|
||||
:key="name_1"
|
||||
:span="item_1.span || 12"
|
||||
:offset="item_1.offset || 0"
|
||||
>
|
||||
<el-form-item :label="$t(item_1.label)" :prop="item_1.field">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<el-tooltip
|
||||
v-if="item_1.tips"
|
||||
popper-class="max-w-96"
|
||||
effect="dark"
|
||||
:content="$t(item_1.tips)"
|
||||
placement="bottom"
|
||||
<div class="pr-8 pt-4">
|
||||
<el-row :gutter="20">
|
||||
<el-col
|
||||
v-for="(item_1, name_1) of subModel(item)"
|
||||
:key="name_1"
|
||||
:span="item_1.span || 12"
|
||||
:offset="item_1.offset || 0"
|
||||
>
|
||||
<el-form-item :label="$t(item_1.label)" :prop="item_1.field">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<el-tooltip
|
||||
v-if="item_1.tips"
|
||||
popper-class="max-w-96"
|
||||
effect="dark"
|
||||
:content="$t(item_1.tips)"
|
||||
placement="bottom"
|
||||
>
|
||||
<el-link
|
||||
class="mr-1 !text-base"
|
||||
icon="InfoFilled"
|
||||
type="warning"
|
||||
:underline="false"
|
||||
>
|
||||
<el-link
|
||||
class="mr-1 !text-base"
|
||||
icon="InfoFilled"
|
||||
type="warning"
|
||||
:underline="false"
|
||||
>
|
||||
</el-link>
|
||||
</el-tooltip>
|
||||
<div class="truncate max-w-56" :title="$t(item_1.label)">
|
||||
{{
|
||||
$t(item_1.label)
|
||||
}}
|
||||
</div>
|
||||
</el-link>
|
||||
</el-tooltip>
|
||||
<div class="truncate max-w-56" :title="$t(item_1.label)">
|
||||
{{ $t(item_1.label) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<component
|
||||
:is="inputModel[item_1.type]"
|
||||
v-model="preferenceData[item_1.field]"
|
||||
v-bind="{
|
||||
preferenceData,
|
||||
deviceScope,
|
||||
title: $t(item_1.placeholder),
|
||||
placeholder: $t(item_1.placeholder),
|
||||
data: item_1,
|
||||
}"
|
||||
></component>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<component
|
||||
:is="inputModel[item_1.type]"
|
||||
v-model="preferenceData[item_1.field]"
|
||||
v-bind="{
|
||||
preferenceData,
|
||||
deviceScope,
|
||||
title: $t(item_1.placeholder),
|
||||
placeholder: $t(item_1.placeholder),
|
||||
data: item_1,
|
||||
}"
|
||||
></component>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
@ -93,9 +84,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { i18n } from '$/locales/index.js'
|
||||
|
||||
import { usePreferenceStore } from '$/store/index.js'
|
||||
|
||||
import { omit } from 'lodash-es'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { inputModel } from './components/index.js'
|
||||
|
||||
@ -114,6 +108,8 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const locale = computed(() => i18n.global.locale.value)
|
||||
|
||||
const preferenceData = defineModel('modelValue', {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
|
@ -129,6 +129,7 @@
|
||||
"device.actions.more.record.name": "Start Recording",
|
||||
"device.actions.more.camera.name": "Startup Camera",
|
||||
"device.actions.more.recordCamera.name": "Record Camera",
|
||||
"device.actions.more.recordAudio.name": "Record Audio",
|
||||
"device.actions.more.otg.name": "Startup OTG",
|
||||
"device.actions.more.custom.name": "Custom Startup",
|
||||
|
||||
@ -317,9 +318,11 @@
|
||||
|
||||
"preferences.record.name": "Recording",
|
||||
"preferences.record.format.name": "Format",
|
||||
"preferences.record.format.placeholder": "mp4",
|
||||
"preferences.record.format.audio.name": "Audio Format",
|
||||
"preferences.record.format.audio.placeholder": "opus",
|
||||
"preferences.record.time-limit.name": "Recording Time Limit",
|
||||
"preferences.record.time-limit.placeholder": "No time limit",
|
||||
"preferences.record.format.placeholder": "mp4",
|
||||
"preferences.record.lock-video-orientation.name": "Video Direction",
|
||||
"preferences.record.lock-video-orientation.placeholder": "Device Orientation",
|
||||
"preferences.record.no-video-playback.name": "Disable Video Playback",
|
||||
|
@ -129,6 +129,7 @@
|
||||
"device.actions.more.record.name": "Начать запись",
|
||||
"device.actions.more.camera.name": "Запустить камеры",
|
||||
"device.actions.more.recordCamera.name": "Запись камеры",
|
||||
"device.actions.more.recordAudio.name": "Записать аудио",
|
||||
"device.actions.more.otg.name": "Запустить OTG",
|
||||
"device.actions.more.custom.name": "Пользовательский запуск",
|
||||
|
||||
@ -317,9 +318,11 @@
|
||||
|
||||
"preferences.record.name": "Запись",
|
||||
"preferences.record.format.name": "Формат",
|
||||
"preferences.record.format.placeholder": "mp4",
|
||||
"preferences.record.format.audio.name": "Аудио формат",
|
||||
"preferences.record.format.audio.placeholder": "opus",
|
||||
"preferences.record.time-limit.name": "Ограничение времени записи",
|
||||
"preferences.record.time-limit.placeholder": "Без ограничения времени",
|
||||
"preferences.record.format.placeholder": "mp4",
|
||||
"preferences.record.lock-video-orientation.name": "Ориентация видео",
|
||||
"preferences.record.lock-video-orientation.placeholder": "Ориентация устройства",
|
||||
"preferences.record.no-video-playback.name": "Отключить воспроизведение видео",
|
||||
|
@ -129,6 +129,7 @@
|
||||
"device.actions.more.record.name": "开始录制",
|
||||
"device.actions.more.camera.name": "启动相机",
|
||||
"device.actions.more.recordCamera.name": "录制相机",
|
||||
"device.actions.more.recordAudio.name": "录制音频",
|
||||
"device.actions.more.otg.name": "启动OTG",
|
||||
"device.actions.more.custom.name": "灵活启动",
|
||||
|
||||
@ -316,8 +317,10 @@
|
||||
"preferences.window.position.y.placeholder": "相对于桌面中心",
|
||||
|
||||
"preferences.record.name": "音视频录制",
|
||||
"preferences.record.format.name": "录制视频格式",
|
||||
"preferences.record.format.name": "视频格式",
|
||||
"preferences.record.format.placeholder": "mp4",
|
||||
"preferences.record.format.audio.name": "音频格式",
|
||||
"preferences.record.format.audio.placeholder": "opus",
|
||||
"preferences.record.time-limit.name": "录制时长",
|
||||
"preferences.record.time-limit.placeholder": "不限时长",
|
||||
"preferences.record.lock-video-orientation.name": "录制视频方向",
|
||||
|
@ -129,6 +129,7 @@
|
||||
"device.actions.more.record.name": "開始錄製",
|
||||
"device.actions.more.camera.name": "啟動鏡頭",
|
||||
"device.actions.more.recordCamera.name": "錄製鏡頭",
|
||||
"device.actions.more.recordAudio.name": "錄製音訊",
|
||||
"device.actions.more.otg.name": "啟動 OTG",
|
||||
"device.actions.more.custom.name": "靈活啟動",
|
||||
|
||||
@ -316,8 +317,10 @@
|
||||
"preferences.window.position.y.placeholder": "相對於桌面中心",
|
||||
|
||||
"preferences.record.name": "影片錄製",
|
||||
"preferences.record.format.name": "錄製影片格式",
|
||||
"preferences.record.format.name": "影片格式",
|
||||
"preferences.record.format.placeholder": "mp4",
|
||||
"preferences.record.format.audio.name": "音訊格式",
|
||||
"preferences.record.format.audio.placeholder": "opus",
|
||||
"preferences.record.time-limit.name": "錄製時長",
|
||||
"preferences.record.time-limit.placeholder": "不限時長",
|
||||
"preferences.record.lock-video-orientation.name": "錄製影片方向",
|
||||
|
@ -46,6 +46,7 @@ export const usePreferenceStore = defineStore({
|
||||
'--video-code',
|
||||
'--audio-code',
|
||||
'--keyboard-inject',
|
||||
'--audio-record-format',
|
||||
...getOtherFields('scrcpy'),
|
||||
],
|
||||
recordKeys,
|
||||
|
@ -19,6 +19,39 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
audioRecordFormat: {
|
||||
label: 'preferences.record.format.audio.name',
|
||||
field: '--audio-record-format',
|
||||
type: 'Select',
|
||||
value: void 0,
|
||||
placeholder: 'preferences.record.format.audio.placeholder',
|
||||
options: [
|
||||
{
|
||||
label: 'opus',
|
||||
value: 'opus',
|
||||
},
|
||||
{
|
||||
label: 'wav',
|
||||
value: 'wav',
|
||||
},
|
||||
{
|
||||
label: 'mka',
|
||||
value: 'mka',
|
||||
},
|
||||
{
|
||||
label: 'flac',
|
||||
value: 'flac',
|
||||
},
|
||||
{
|
||||
label: 'aac',
|
||||
value: 'aac',
|
||||
},
|
||||
{
|
||||
label: 'm4a',
|
||||
value: 'm4a',
|
||||
},
|
||||
],
|
||||
},
|
||||
lockVideoOrientation: {
|
||||
label: 'preferences.record.lock-video-orientation.name',
|
||||
field: '--lock-video-orientation',
|
||||
|
Loading…
Reference in New Issue
Block a user