You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
projectx/src/lib/ObsVue.vue

406 lines
20 KiB

<template>
<v-card class="fill-height align-center">
<v-dialog v-model="fileSystem">
<v-card>
<v-card-title>File System</v-card-title>
<v-card-text>
<v-file-input label="Upload" id="ufile"></v-file-input><v-btn @click="uploadfile">upload</v-btn>
<v-row>
<v-col cols="12" md="2" v-for="file in files" :key="file">
<v-card>
{{file}}
</v-card>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-dialog>
<v-dialog v-model="createSceneModel" max-width="300px">
<v-card>
<v-card-title>New Scene</v-card-title>
<v-card-text>
<v-text-field v-model="sceneName" label="Scene Name"></v-text-field>
</v-card-text>
<v-card-actions>
<v-btn text @click="createSceneModel=false">Cancel</v-btn>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="createScene">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="createSceneItem" max-width="300px">
<v-card>
<v-card-title>New Source</v-card-title>
<v-card-text>
<v-text-field v-model="sourceName" label="Source Name"></v-text-field>
<v-select v-model="sourceType" item-value="value" item-text="name" :items="[{name:'Image', value:'image_source'},{name: 'VLC Source', value: 'vlc_source'},{name: 'Media Source', value: 'ffmpeg_source'},{name: 'Text', value: 'text_ft2_source_v2'}]" label="Source Type"></v-select>
<v-text-field label="Image Path" v-model="sourceSettings.file" v-if="sourceType === 'image_source'"></v-text-field>
<v-text-field label="File Path" v-model="sourceSettings.localFile" v-if="sourceType === 'ffmpeg_source'"></v-text-field>
<div v-if="sourceType === 'vlc_source'">
<div v-for="(file, index) in sourceSettings.playlist" :key="index">
{{file}}
</div>
</div>
<v-text-field v-if="sourceType === 'vlc_source'" v-model="sourceSettings.file"></v-text-field><v-btn small text @click="addPlaylist(sourceSettings.file)">+</v-btn>
</v-card-text>
<v-card-actions>
<v-btn text @click="createSceneItem=false">Cancel</v-btn>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="createSource">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-card-text>
<v-row>
<v-col cols="12" md="9">
<v-card ref="mainvid" id="mainvid"
:style="`font-size:10px;height: ${vidheight}px;background: #ccc;position: relative`"
v-if="selecteScene">
<div :style="`border:1px solid #ccc;width:${source.cx*vidperm}px;z-index:${selecteScene.sources.length - index};height:${source.cy*vidperm}px;background-size: 100% 100%;top:${source.y*vidperm}px;left:${source.x*vidperm}px;position:absolute;min-width:50px;min-height:50px;background:url()`"
v-for="(source,index) in selecteScene.sources" :key="index">
<div style="top:0;left:0;position: absolute;color:#fff;text-shadow: #000 1px 1px">
{{source.name}} ({{source.id}})
</div>
<div style="top:0;right:0;position: absolute;color:#fff;text-shadow: #000 1px 1px">
{{source.type}} ({{source.source_cx}} x {{source.source_cy}} )
</div>
<img v-if="source.srcdata" width="100%" height="100%" :src="source.srcdata"/>
</div>
</v-card>
</v-col>
<v-col cols="12" md="3">
<v-card v-if="selectedItemProps">
<v-card-text>
<v-text-field label="Name" v-model="selectedItemProps.name"></v-text-field>
<v-text-field :label="`Width (Source: ${selectedItemProps.sourceWidth})`"
v-model="selectedItemProps.width" @keyup="selectedItemProps.height=selectedItemProps.width * (selectedItemProps.sourceHeight/selectedItemProps.sourceWidth)"></v-text-field>
<v-text-field :label="`Height (Source: ${selectedItemProps.sourceHeight})`"
v-model="selectedItemProps.height"></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn small @click="saveSelectedItem">Save</v-btn>
</v-card-actions>
</v-card>
<br/>
<v-card v-if="selectedItemSourceProps">
<v-card-title>Source Options
<v-spacer></v-spacer>
<v-btn icon x-smal @click="panels.source = !panels.source">
<v-icon>mdi-menu</v-icon>
</v-btn>
</v-card-title>
<v-card-text v-show="panels.source">
<v-text-field v-if="selectedItemSourceProps.sourceType === 'xcomposite_input'"
label="Capture Window"
v-model="selectedItemSourceProps.sourceSettings.capture_window"></v-text-field>
<v-text-field v-if="selectedItemSourceProps.sourceType === 'image_source'" label="File"
v-model="selectedItemSourceProps.sourceSettings.file"></v-text-field>
<div v-if="selectedItemSourceProps.sourceType === 'vlc_source'">
<div v-for="(item, index) in selectedItemSourceProps.sourceSettings.playlist"
:key="index">
<v-row>
<v-col cols="12" md="10">{{item.value}}</v-col>
<v-col cols="12" md="2">
<v-btn icon small
@click="selectedItemSourceProps.sourceSettings.playlist.splice(index,1)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</v-col>
</v-row>
</div>
<v-text-field v-if="selectedItemSourceProps.sourceType === 'vlc_source'" label="File"
v-model="selectedItemSourceProps.file"></v-text-field>
<v-spacer></v-spacer>
<v-btn small
@click="selectedItemSourceProps.sourceSettings.playlist.push({ hidden: false, selected: false, value: selectedItemSourceProps.file}); selectedItemSourceProps.file=''">
Add To Playlist
</v-btn>
</div>
</v-card-text>
<v-card-actions v-show="panels.source">
<v-spacer></v-spacer>
<v-btn small>Save</v-btn>
</v-card-actions>
</v-card>
<br/>
<v-card v-if="selectedItemProps">
<v-card-title>Position
<v-spacer></v-spacer>
<v-btn icon x-smal @click="panels.position = !panels.position" l>
<v-icon>mdi-menu</v-icon>
</v-btn>
</v-card-title>
<v-card-text v-show="panels.position">
<v-text-field label="X" v-model="selectedItemProps.position.x"></v-text-field>
<v-text-field label="Y" v-model="selectedItemProps.position.y"></v-text-field>
<v-text-field label="Rotation" v-model="selectedItemProps.rotation"></v-text-field>
</v-card-text>
<v-card-actions v-show="panels.position">
<v-spacer></v-spacer>
<v-btn small>Save</v-btn>
</v-card-actions>
</v-card>
<br/>
<v-card v-if="selectedItemProps">
<v-card-title>Crop
<v-spacer></v-spacer>
<v-btn icon x-smal @click="panels.crop = !panels.crop">
<v-icon>mdi-menu</v-icon>
</v-btn>
</v-card-title>
<v-card-text v-show="panels.crop">
<v-text-field label="Top" v-model="selectedItemProps.crop.top"></v-text-field>
<v-text-field label="Left" v-model="selectedItemProps.crop.left"></v-text-field>
<v-text-field label="Bottom" v-model="selectedItemProps.crop.bottom"></v-text-field>
<v-text-field label="Right" v-model="selectedItemProps.crop.right"></v-text-field>
</v-card-text>
<v-card-actions v-show="panels.crop">
<v-spacer></v-spacer>
<v-btn small>Save</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="3">
<v-list>
<v-list-item-group v-model="selecteSceneName" color="primary">
<v-list-item v-for="(scene,index) in scenes" :key="index" @click="setSelect(scene)">
<v-list-item-content>
<v-list-item-title v-text="scene.name"></v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-content>
<v-list-item-title @click="createSceneModel=true">New Scene</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
</v-col>
<v-col cols="12" md="3">
<v-list v-if="selecteScene">
<v-list-item v-for="(source,index) in selecteScene.sources" :key="index"
@click="setItemSelect(source)">
<v-list-item-content>
<v-list-item-title v-text="source.name"></v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-content>
<v-list-item-title @click="createSceneItem=true">New Item</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-col>
</v-row>
</v-card-text>
</v-card>
</template>
<script>
const OBSWebSocket = require('obs-websocket-js');
export default {
name: "ObsVue",
props: {
server: String
},
data: () => ({
obs: null,
selectedItemProps: null,
selectedItemSourceProps: null,
createSceneModel: false,
createSceneItem: false,
sourceSettings: {
playlist: [],
file: '',
localFile: ''
},
files: [
'test.jpg',
'test.png'
],
sourceType: '',
sourceName: '',
scenes: [],
sources: [],
panels: {
source: false,
position: false,
crop: false
},
previewInterval: 0,
selecteScene: null,
sceneName: '',
vidheight: 0,
vidperm: 0,
selecteSceneName: null,
fileSystem: true
}),
mounted() {
this.obs = new OBSWebSocket()
this.getfiles()
this.obs.connect({address: 'ws://localhost:4444', password: 'neverdie'}).then(this.connected)
this.obs.on('error', err => {
console.error('socket error:', err);
});
},
methods: {
uploadfile() {
var file = document.getElementById('ufile')
console.log(file.files[0])
var filereader = new FileReader()
filereader.onloadend = () => {
this.$axios.post('http://localhost:5000/api/upload', {"file": filereader.result.split(';base64,')[1], 'file_name': file.files[0].name}).then(this.getfiles)
}
filereader.readAsDataURL(file.files[0]);
},
getfiles () {
this.$axios.get('http://localhost:5000/api/files').then(result => {
this.files = result.data
})
},
addPlaylist(item) {
this.sourceSettings.playlist.push({hidden: false, selected: false, value:item})
console.log(this.sourceSettings)
},
createScene() {
this.obs.send('CreateNewScene', {'sceneName': this.sceneName}).then(response => {
console.log(response)
this.sceneName = ''
this.createSceneModel = false
this.sceneList()
})
},
createSource() {
var sourceSetting;
if (this.sourceType === 'vlc_source') sourceSetting = {playlist: this.sourceSettings.playlist}
if (this.sourceType === 'ffmpeg_source') sourceSetting = {localfile: this.sourceSettings.localfile}
if (this.sourceType === 'image_source') sourceSetting = {file: this.sourceSettings.file}
console.log({sourceName: this.sourceName,sourceSettings: sourceSetting, sourceType: this.sourceType })
this.obs.send('CreateNewSource', {sourceName: this.sourceName,sourceSettings: sourceSetting, sourceType: this.sourceType }).then(response => {
console.log(response)
this.sceneName = ''
this.createSceneModel = false
this.obs.send('AddToScene', {sourceName:this.sourceName })
this.sceneList()
})
},
onAuth() {
console.log("auth")
},
newScene() {
},
setItemSelect(item) {
this.obs.send("GetSceneItemProperties", {
item: item.name,
"scene-name": this.selecteScene.name
}).then(data => {
console.log("GetSceneItemProperties")
console.log(data)
this.selectedItemProps = data
})
this.obs.send("GetSourceSettings", {sourceName: item.name}).then(data => {
console.log("GetSourceSettings")
console.log(data)
this.selectedItemSourceProps = data
})
},
setSelect(item) {
console.log(item)
this.selecteScene = item
this.selecteSceneName = item.name
this.obs.send('GetSourcesList').then(data => {
console.log('GetSourcesList')
console.log(data)
})
if (this.previewInterval > 0) clearInterval(this.previewInterval)
this.previewInterval = setInterval(() => {
this.selecteScene.sources.forEach(sitem => {
this.obs.send('TakeSourceScreenshot', {
sourceName: sitem.name,
embedPictureFormat: 'png'
}).then(data => {
sitem.srcdata = data.img
this.selecteScene.__ob__.dep.notify()
this.vidheight = document.getElementById('mainvid').offsetWidth / (16 / 9)
this.vidperm = this.vidheight / 1080.0
}).catch(err => {
console.log(err)
})
})
}, 500)
},
saveSelectedItem() {
console.log( {
'item': this.selectedItemProps.name,
position: {
x: parseInt(this.selectedItemProps.position.x),
y: parseInt(this.selectedItemProps.position.y),
},
crop: this.selectedItemProps.crop,
rotation: this.selectedItemProps.rotation,
height: this.selectedItemProps.height,
scale: {x:this.selectedItemProps.width/this.selectedItemProps.sourceWidth,y:this.selectedItemProps.height/this.selectedItemProps.sourceHeight}
})
this.obs.send('SetSceneItemProperties', {
item: this.selectedItemProps.name,
position: {
x: parseInt(this.selectedItemProps.position.x),
y: parseInt(this.selectedItemProps.position.y),
},
crop: {
top:parseInt(this.selectedItemProps.crop.top),
bottom:parseInt(this.selectedItemProps.crop.bottom),
left:parseInt(this.selectedItemProps.crop.left),
right:parseInt(this.selectedItemProps.crop.right),
},
rotation: this.selectedItemProps.rotation,
height: this.selectedItemProps.height,
scale: {x:this.selectedItemProps.width/this.selectedItemProps.sourceWidth,y:this.selectedItemProps.height/this.selectedItemProps.sourceHeight}
}).then(data => {
console.log(data)
this.sceneList()
})
},
sceneList() {
this.obs.send('GetSceneList').then(data => {
console.log("scene", data)
this.scenes = data.scenes
data.scenes.forEach(item => {
if (item.name === data["current-scene"]) {
this.setSelect(item)
}
})
})
},
connected() {
this.obs.send('GetVersion').then(data => {
this.obs.send('GetVersion').then(data2 => {
console.log(data)
console.log(data2)
})
})
this.sceneList()
}
}
}
</script>
<style scoped>
</style>