wco_models 3.1.0.313 → 3.1.0.314
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.txt +19 -4
- data/app/assets/stylesheets/wco/main.scss +4 -0
- data/app/assets/stylesheets/wco/newsvideos.scss +10 -2
- data/app/controllers/wco/api/leads_controller.rb +5 -2
- data/app/controllers/wco/api/newspartials_controller.rb +15 -4
- data/app/controllers/wco/api/newsproducer_controller.rb +26 -0
- data/app/controllers/wco/api/newsvideos_controller.rb +17 -3
- data/app/controllers/wco/api/tags_controller.rb +2 -0
- data/app/controllers/wco/api/videos_controller.rb +3 -3
- data/app/controllers/wco/api_controller.rb +9 -9
- data/app/controllers/wco/newsvideos_controller.rb +102 -1
- data/app/models/wco/newspartial.rb +7 -3
- data/app/models/wco/newsvideo.rb +93 -78
- data/app/models/wco/tag.rb +4 -0
- data/app/models/wco_email/context.rb +11 -0
- data/app/models/wco_email/email_filter_condition.rb +17 -1
- data/app/views/wco/api/newsproducer/README.txt +2 -0
- data/app/views/wco/{newsproducer → api/newsproducer}/_studio_1.js +111 -104
- data/app/views/wco/{newsproducer → api/newsproducer}/studio_1.html.erb +4 -3
- data/app/views/wco/api/newsvideos/show.jbuilder +13 -0
- data/app/views/wco/newspartials/_form.haml +4 -2
- data/app/views/wco/newspartials/_show_in_newsvideo.haml +3 -3
- data/app/views/wco/newsvideos/_form.haml +19 -6
- data/app/views/wco/newsvideos/edit.haml +2 -1
- data/app/views/wco/newsvideos/show.haml +9 -2
- data/config/initializers/08_integrations.rb +2 -0
- data/config/initializers/08_integrations.rb-example +2 -0
- data/config/routes.rb +12 -4
- metadata +9 -8
- data/app/controllers/wco/api/obfuscated_redirects_controller.rb +0 -26
- data/app/controllers/wco/newsproducer_controller.rb +0 -22
- /data/app/views/wco/{newsproducer → api/newsproducer}/canvas.html.erb +0 -0
- /data/app/views/wco/{newsproducer → api/newsproducer}/canvas_minimal.html.erb +0 -0
|
@@ -150,6 +150,17 @@ class WcoEmail::Context
|
|
|
150
150
|
})
|
|
151
151
|
end
|
|
152
152
|
|
|
153
|
+
def self.new_for message
|
|
154
|
+
self.new({
|
|
155
|
+
from_email: message.to&.downcase,
|
|
156
|
+
lead_id: message.lead_id,
|
|
157
|
+
subject: message.subject,
|
|
158
|
+
reply_to_message: message,
|
|
159
|
+
email_template_id: ET.find_by( slug: 'blank').id,
|
|
160
|
+
})
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
|
|
153
164
|
end
|
|
154
165
|
Ctx = WcoEmail::Context
|
|
155
166
|
|
|
@@ -47,6 +47,12 @@ class WcoEmail::EmailFilterCondition
|
|
|
47
47
|
|
|
48
48
|
field :value
|
|
49
49
|
validates :value, presence: true
|
|
50
|
+
before_validation :strip_value
|
|
51
|
+
def strip_value
|
|
52
|
+
self.value = value.strip
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
field :comment
|
|
50
56
|
|
|
51
57
|
|
|
52
58
|
def apply lead:, message:
|
|
@@ -62,6 +68,16 @@ class WcoEmail::EmailFilterCondition
|
|
|
62
68
|
end
|
|
63
69
|
end
|
|
64
70
|
|
|
71
|
+
when WcoEmail::EmailFilterCondition::FIELD_LEADSET
|
|
72
|
+
if cond.operator == WcoEmail::EmailFilterCondition::OPERATOR__ID
|
|
73
|
+
test_leadset = Wco::Leadset.find( value ) rescue nil
|
|
74
|
+
if test_leadset
|
|
75
|
+
if lead.leadset == test_leadset
|
|
76
|
+
reason = "#{email_skip_filter ? 'skip_' : ''}condition leadset _id `#{value}`"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
65
81
|
when WcoEmail::EmailFilterCondition::FIELD_TAGGED
|
|
66
82
|
## cond.operator should eql OPERATOR__ID but I don't check b/c if its slug, it should work also.
|
|
67
83
|
tag = Wco::Tag.find( cond.value ) rescue nil
|
|
@@ -98,7 +114,7 @@ class WcoEmail::EmailFilterCondition
|
|
|
98
114
|
"<EF#{email_skip_filter ? 'Skip' : ''}Condition #{field} #{operator} `#{value}` />"
|
|
99
115
|
end
|
|
100
116
|
def to_s_full indent: 0
|
|
101
|
-
"#{" " * indent }<EF#{email_skip_filter ? 'Skip' : ''}Condition #{field} #{operator} `#{value}` />\n"
|
|
117
|
+
"#{" " * indent }<EF#{email_skip_filter ? 'Skip' : ''}Condition #{field} #{operator} `#{value}` #{comment} />\n"
|
|
102
118
|
end
|
|
103
119
|
|
|
104
120
|
|
|
@@ -3,23 +3,23 @@
|
|
|
3
3
|
**/
|
|
4
4
|
const logg = (a, b="", c=null) => {
|
|
5
5
|
if ('undefined' === typeof window) { return }
|
|
6
|
-
c = "string" === typeof c ? c : b.replace(/\W/g,
|
|
6
|
+
c = "string" === typeof c ? c : b.replace(/\W/g, '')
|
|
7
7
|
if (c.length > 0) {
|
|
8
|
-
window[c] = a
|
|
8
|
+
window[c] = a
|
|
9
9
|
}
|
|
10
|
-
console.log(`+++ ${b}:`, a)
|
|
11
|
-
}
|
|
10
|
+
console.log(`+++ ${b}:`, a) // eslint-disable-line no-console
|
|
11
|
+
}
|
|
12
12
|
|
|
13
13
|
let avatar_url = 'https://cdn.jsdelivr.net/gh/wasya-co/ishlib3js@0.0.3/public/vendor/models/avatars/brunette.glb'
|
|
14
14
|
|
|
15
|
-
import * as THREE from 'three'
|
|
15
|
+
import * as THREE from 'three'
|
|
16
16
|
|
|
17
|
-
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
|
|
18
|
-
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
|
|
17
|
+
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
|
|
18
|
+
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
|
|
19
19
|
|
|
20
|
-
import { TalkingHead } from "talkinghead"
|
|
20
|
+
import { TalkingHead } from "talkinghead"
|
|
21
21
|
|
|
22
|
-
const params = new URLSearchParams(window.location.search)
|
|
22
|
+
const params = new URLSearchParams(window.location.search)
|
|
23
23
|
|
|
24
24
|
let config = {
|
|
25
25
|
sampleRate: 8000,
|
|
@@ -29,22 +29,23 @@ let config = {
|
|
|
29
29
|
lipsyncLang: "en",
|
|
30
30
|
waitForAudioChunks: false,
|
|
31
31
|
enableMetrics: false,
|
|
32
|
-
}
|
|
33
|
-
let width =
|
|
34
|
-
let height =
|
|
35
|
-
|
|
32
|
+
}
|
|
33
|
+
let width = 50
|
|
34
|
+
let height = 50
|
|
35
|
+
let slug = '<ccapture>'
|
|
36
|
+
const FPS = 24
|
|
36
37
|
|
|
37
|
-
let frame = 0
|
|
38
|
+
let frame = 0
|
|
38
39
|
const api_key = params.get('api_key')
|
|
39
40
|
const api_secret = params.get('api_secret')
|
|
40
41
|
const wco_origin = params.get('wco_origin')
|
|
41
42
|
const newspartial_id = params.get('newspartial_id')
|
|
42
43
|
let totalFrames
|
|
43
44
|
|
|
44
|
-
let camera, controls, head, renderer, scene
|
|
45
|
-
let faceTarget = new THREE.Vector3()
|
|
46
|
-
let chunkedInput = null
|
|
47
|
-
var capturer = new CCapture( { format: 'webm', framerate: FPS } )
|
|
45
|
+
let camera, controls, head, renderer, scene
|
|
46
|
+
let faceTarget = new THREE.Vector3()
|
|
47
|
+
let chunkedInput = null
|
|
48
|
+
var capturer = new CCapture( { format: 'webm', framerate: FPS } )
|
|
48
49
|
|
|
49
50
|
async function init() {
|
|
50
51
|
if (newspartial_id) {
|
|
@@ -55,20 +56,23 @@ async function init() {
|
|
|
55
56
|
if (typeof chunkedInput === 'string') {
|
|
56
57
|
chunkedInput = JSON.parse(chunkedInput)
|
|
57
58
|
}
|
|
58
|
-
logg(chunkedInput, 'chunkedInput')
|
|
59
|
+
// logg(chunkedInput, 'chunkedInput')
|
|
59
60
|
const last = chunkedInput.wtimes.length-1
|
|
60
61
|
const duration_ms = chunkedInput.wtimes[last] + chunkedInput.wdurations[last]
|
|
61
62
|
logg(duration_ms, 'duration_ms')
|
|
62
|
-
totalFrames = duration_ms/1000*FPS
|
|
63
|
+
totalFrames = duration_ms/1000*FPS
|
|
64
|
+
width = chunkedInput.w_px
|
|
65
|
+
height = chunkedInput.h_px
|
|
66
|
+
slug = chunkedInput.slug
|
|
63
67
|
} catch (error) {
|
|
64
|
-
console.log(error)
|
|
65
|
-
chunkedInput = null
|
|
66
|
-
totalFrames = undefined
|
|
68
|
+
console.log(error)
|
|
69
|
+
chunkedInput = null
|
|
70
|
+
totalFrames = undefined
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
scene = new THREE.Scene()
|
|
71
|
-
scene.background = new THREE.Color(0xd3d3d3)
|
|
74
|
+
scene = new THREE.Scene()
|
|
75
|
+
scene.background = new THREE.Color(0xd3d3d3)
|
|
72
76
|
|
|
73
77
|
/* fov — Camera frustum vertical field of view.
|
|
74
78
|
* aspect — Camera frustum aspect ratio.
|
|
@@ -79,28 +83,28 @@ async function init() {
|
|
|
79
83
|
camera.position.set( 0, 2, 8 )
|
|
80
84
|
camera.lookAt( 0, 0, 0 )
|
|
81
85
|
|
|
82
|
-
const ambientLight = new THREE.AmbientLight( 0xffffff )
|
|
83
|
-
scene.add( ambientLight )
|
|
86
|
+
const ambientLight = new THREE.AmbientLight( 0xffffff )
|
|
87
|
+
scene.add( ambientLight )
|
|
84
88
|
|
|
85
|
-
const grid = new THREE.GridHelper(10, 10, 0x888888, 0xbbbbbb)
|
|
86
|
-
grid.position.y = 0
|
|
87
|
-
scene.add(grid)
|
|
89
|
+
const grid = new THREE.GridHelper(10, 10, 0x888888, 0xbbbbbb)
|
|
90
|
+
grid.position.y = 0
|
|
91
|
+
scene.add(grid)
|
|
88
92
|
|
|
89
|
-
const nodeAvatar = document.getElementById('avatar')
|
|
93
|
+
const nodeAvatar = document.getElementById('avatar')
|
|
90
94
|
head = new TalkingHead( nodeAvatar, {
|
|
91
95
|
avatarOnly: true,
|
|
92
96
|
avatarOnlyScene: scene,
|
|
93
97
|
avatarOnlyCamera: camera,
|
|
94
98
|
|
|
95
99
|
lipsyncModules: ["en"],
|
|
96
|
-
})
|
|
97
|
-
logg(head, 'head')
|
|
100
|
+
})
|
|
101
|
+
// logg(head, 'head')
|
|
98
102
|
|
|
99
103
|
|
|
100
104
|
|
|
101
|
-
const nodeLoading = document.getElementById('loading')
|
|
105
|
+
const nodeLoading = document.getElementById('loading')
|
|
102
106
|
try {
|
|
103
|
-
nodeLoading.textContent = "Loading..."
|
|
107
|
+
nodeLoading.textContent = "Loading..."
|
|
104
108
|
await head.showAvatar( {
|
|
105
109
|
url: avatar_url,
|
|
106
110
|
body: 'F',
|
|
@@ -108,41 +112,41 @@ async function init() {
|
|
|
108
112
|
lipsyncLang: 'en'
|
|
109
113
|
}, (ev) => {
|
|
110
114
|
if ( ev.lengthComputable ) {
|
|
111
|
-
let val = Math.min(100,Math.round(ev.loaded/ev.total * 100 ))
|
|
112
|
-
nodeLoading.textContent = "Loading " + val + "%"
|
|
115
|
+
let val = Math.min(100,Math.round(ev.loaded/ev.total * 100 ))
|
|
116
|
+
nodeLoading.textContent = "Loading " + val + "%"
|
|
113
117
|
}
|
|
114
|
-
})
|
|
115
|
-
nodeLoading.style.display = 'none'
|
|
118
|
+
})
|
|
119
|
+
nodeLoading.style.display = 'none'
|
|
116
120
|
|
|
117
|
-
head.armature.position.set(0, 0, 0)
|
|
118
|
-
head.armature.rotation.set(0, 0, 0)
|
|
119
|
-
scene.add(head.armature)
|
|
121
|
+
head.armature.position.set(0, 0, 0)
|
|
122
|
+
head.armature.rotation.set(0, 0, 0)
|
|
123
|
+
scene.add(head.armature)
|
|
120
124
|
|
|
121
125
|
// Put feet at the origin
|
|
122
|
-
head.armature.updateMatrixWorld(true)
|
|
123
|
-
const leftToe = new THREE.Vector3()
|
|
124
|
-
const rightToe = new THREE.Vector3()
|
|
125
|
-
head.objectLeftToeBase.getWorldPosition(leftToe)
|
|
126
|
-
head.objectRightToeBase.getWorldPosition(rightToe)
|
|
126
|
+
head.armature.updateMatrixWorld(true)
|
|
127
|
+
const leftToe = new THREE.Vector3()
|
|
128
|
+
const rightToe = new THREE.Vector3()
|
|
129
|
+
head.objectLeftToeBase.getWorldPosition(leftToe)
|
|
130
|
+
head.objectRightToeBase.getWorldPosition(rightToe)
|
|
127
131
|
head.armature.position.set(
|
|
128
132
|
-(leftToe.x + rightToe.x) / 2,
|
|
129
133
|
-Math.min(leftToe.y, rightToe.y),
|
|
130
134
|
-(leftToe.z + rightToe.z) / 2
|
|
131
|
-
)
|
|
132
|
-
head.armature.updateMatrixWorld(true)
|
|
135
|
+
)
|
|
136
|
+
head.armature.updateMatrixWorld(true)
|
|
133
137
|
|
|
134
138
|
// Camera at head level, pointed at the face
|
|
135
|
-
const leftEye = new THREE.Vector3()
|
|
136
|
-
const rightEye = new THREE.Vector3()
|
|
137
|
-
head.objectLeftEye.getWorldPosition(leftEye)
|
|
138
|
-
head.objectRightEye.getWorldPosition(rightEye)
|
|
139
|
-
faceTarget.copy(leftEye).add(rightEye).multiplyScalar(0.5)
|
|
140
|
-
|
|
141
|
-
const camPos = new THREE.Vector3(0, 0, 2)
|
|
142
|
-
camPos.applyQuaternion(head.armature.quaternion)
|
|
143
|
-
camPos.add(faceTarget)
|
|
144
|
-
camera.position.copy(camPos)
|
|
145
|
-
camera.lookAt(faceTarget)
|
|
139
|
+
const leftEye = new THREE.Vector3()
|
|
140
|
+
const rightEye = new THREE.Vector3()
|
|
141
|
+
head.objectLeftEye.getWorldPosition(leftEye)
|
|
142
|
+
head.objectRightEye.getWorldPosition(rightEye)
|
|
143
|
+
faceTarget.copy(leftEye).add(rightEye).multiplyScalar(0.5)
|
|
144
|
+
|
|
145
|
+
const camPos = new THREE.Vector3(0, 0, 2)
|
|
146
|
+
camPos.applyQuaternion(head.armature.quaternion)
|
|
147
|
+
camPos.add(faceTarget)
|
|
148
|
+
camera.position.copy(camPos)
|
|
149
|
+
camera.lookAt(faceTarget)
|
|
146
150
|
|
|
147
151
|
await head.streamStart({
|
|
148
152
|
sampleRate: config.sampleRate,
|
|
@@ -155,8 +159,8 @@ async function init() {
|
|
|
155
159
|
})
|
|
156
160
|
|
|
157
161
|
} catch (error) {
|
|
158
|
-
console.log(error)
|
|
159
|
-
nodeLoading.textContent = error.toString()
|
|
162
|
+
console.log(error)
|
|
163
|
+
nodeLoading.textContent = error.toString()
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
|
|
@@ -165,41 +169,41 @@ async function init() {
|
|
|
165
169
|
renderer = new THREE.WebGLRenderer( {
|
|
166
170
|
alpha: false,
|
|
167
171
|
antialias: true,
|
|
168
|
-
} )
|
|
169
|
-
renderer.setClearColor(0xd3d3d3, 1)
|
|
170
|
-
renderer.setPixelRatio( 1 ); // window.devicePixelRatio )
|
|
171
|
-
renderer.setSize( width, height )
|
|
172
|
-
renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
173
|
-
renderer.toneMappingExposure = 1
|
|
174
|
-
renderer.outputColorSpace = THREE.SRGBColorSpace
|
|
175
|
-
document.getElementById('rotatingC').appendChild( renderer.domElement )
|
|
172
|
+
} )
|
|
173
|
+
renderer.setClearColor(0xd3d3d3, 1)
|
|
174
|
+
renderer.setPixelRatio( 1 ); // window.devicePixelRatio )
|
|
175
|
+
renderer.setSize( width, height )
|
|
176
|
+
renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
177
|
+
renderer.toneMappingExposure = 1
|
|
178
|
+
renderer.outputColorSpace = THREE.SRGBColorSpace
|
|
179
|
+
document.getElementById('rotatingC').appendChild( renderer.domElement )
|
|
176
180
|
|
|
177
181
|
//
|
|
178
182
|
|
|
179
|
-
controls = new OrbitControls( camera, renderer.domElement )
|
|
180
|
-
controls.enableDamping = true
|
|
181
|
-
controls.enableRotate = true
|
|
182
|
-
controls.enablePan = true
|
|
183
|
-
controls.enableZoom = true
|
|
184
|
-
controls.minDistance = 0.5
|
|
185
|
-
controls.maxDistance = 100
|
|
186
|
-
controls.target.copy(faceTarget)
|
|
187
|
-
controls.autoRotate = false
|
|
188
|
-
controls.update()
|
|
183
|
+
controls = new OrbitControls( camera, renderer.domElement )
|
|
184
|
+
controls.enableDamping = true
|
|
185
|
+
controls.enableRotate = true
|
|
186
|
+
controls.enablePan = true
|
|
187
|
+
controls.enableZoom = true
|
|
188
|
+
controls.minDistance = 0.5
|
|
189
|
+
controls.maxDistance = 100
|
|
190
|
+
controls.target.copy(faceTarget)
|
|
191
|
+
controls.autoRotate = false
|
|
192
|
+
controls.update()
|
|
189
193
|
|
|
190
194
|
//
|
|
191
195
|
|
|
192
|
-
window.addEventListener( 'resize', onWindowResize )
|
|
196
|
+
window.addEventListener( 'resize', onWindowResize )
|
|
193
197
|
|
|
194
198
|
|
|
195
199
|
// Keep rendering so OrbitControls drag/damping stay live
|
|
196
|
-
renderer.setAnimationLoop(animate)
|
|
200
|
+
renderer.setAnimationLoop(animate)
|
|
197
201
|
|
|
198
202
|
// Start capture/audio only after the renderer exists
|
|
199
203
|
if (newspartial_id && chunkedInput) {
|
|
200
|
-
capturer.start()
|
|
204
|
+
capturer.start()
|
|
201
205
|
logg('capturer.start')
|
|
202
|
-
head.streamAudio(chunkedInput)
|
|
206
|
+
head.streamAudio(chunkedInput)
|
|
203
207
|
}
|
|
204
208
|
}
|
|
205
209
|
|
|
@@ -212,29 +216,29 @@ document.addEventListener('DOMContentLoaded', async function(e) {
|
|
|
212
216
|
})
|
|
213
217
|
|
|
214
218
|
function onWindowResize() {
|
|
215
|
-
camera.aspect = width / height
|
|
216
|
-
camera.updateProjectionMatrix()
|
|
217
|
-
renderer.setSize( width, height )
|
|
218
|
-
render()
|
|
219
|
+
camera.aspect = width / height
|
|
220
|
+
camera.updateProjectionMatrix()
|
|
221
|
+
renderer.setSize( width, height )
|
|
222
|
+
render()
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
function render() {
|
|
222
|
-
renderer.render( scene, camera )
|
|
226
|
+
renderer.render( scene, camera )
|
|
223
227
|
}
|
|
224
228
|
|
|
225
229
|
function animate() {
|
|
226
|
-
const t = frame / FPS
|
|
227
|
-
if (head) head.animate(1000/FPS)
|
|
228
|
-
controls.update()
|
|
229
|
-
renderer.render( scene, camera )
|
|
230
|
+
const t = frame / FPS
|
|
231
|
+
if (head) head.animate(1000/FPS)
|
|
232
|
+
controls.update()
|
|
233
|
+
renderer.render( scene, camera )
|
|
230
234
|
|
|
231
235
|
if (totalFrames) {
|
|
232
|
-
capturer.capture( renderer.domElement )
|
|
233
|
-
frame
|
|
236
|
+
capturer.capture( renderer.domElement )
|
|
237
|
+
frame++
|
|
234
238
|
if (frame >= totalFrames) {
|
|
235
239
|
totalFrames = false
|
|
236
|
-
renderer.setAnimationLoop(null)
|
|
237
|
-
capturer.stop()
|
|
240
|
+
renderer.setAnimationLoop(null)
|
|
241
|
+
capturer.stop()
|
|
238
242
|
logg('capturer.stop')
|
|
239
243
|
|
|
240
244
|
if (newspartial_id) {
|
|
@@ -242,9 +246,9 @@ function animate() {
|
|
|
242
246
|
logg(blob, 'blob')
|
|
243
247
|
renderer.domElement.toBlob((thumb) => {
|
|
244
248
|
logg(thumb, 'thumb')
|
|
245
|
-
const form = new FormData()
|
|
249
|
+
const form = new FormData()
|
|
246
250
|
form.append('video', blob, 'lips.webm')
|
|
247
|
-
form.append('name',
|
|
251
|
+
form.append('name', slug)
|
|
248
252
|
form.append('thumb', thumb)
|
|
249
253
|
form.append('newspartial_id', newspartial_id)
|
|
250
254
|
|
|
@@ -254,26 +258,29 @@ function animate() {
|
|
|
254
258
|
// 'Content-Type': 'video/webm',
|
|
255
259
|
},
|
|
256
260
|
body: form,
|
|
261
|
+
}).then(() => {
|
|
262
|
+
document.getElementById('status').textContent = 'finished'
|
|
263
|
+
document.body.style.backgroundColor = 'gray'
|
|
257
264
|
})
|
|
258
265
|
})
|
|
259
|
-
})
|
|
266
|
+
})
|
|
260
267
|
}
|
|
261
268
|
// Resume interactive orbit after capture
|
|
262
|
-
renderer.setAnimationLoop(animate)
|
|
269
|
+
renderer.setAnimationLoop(animate)
|
|
263
270
|
}
|
|
264
271
|
}
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
|
|
268
275
|
// Speak when clicked
|
|
269
|
-
const nodeSpeak = document.getElementById('speak')
|
|
276
|
+
const nodeSpeak = document.getElementById('speak')
|
|
270
277
|
nodeSpeak.addEventListener('click', function () {
|
|
271
278
|
try {
|
|
272
279
|
|
|
273
280
|
} catch (error) {
|
|
274
|
-
console.log(error)
|
|
281
|
+
console.log(error)
|
|
275
282
|
}
|
|
276
|
-
})
|
|
283
|
+
})
|
|
277
284
|
|
|
278
285
|
|
|
279
286
|
console.log('+++ loaded wco_models :: newsproducer :: studio_1.js')
|
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
}
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Status:<span id='status'>pending</span>
|
|
17
|
+
|
|
17
18
|
<button id='speak'>Speak</button>
|
|
18
19
|
<div id='avatar'></div>
|
|
19
20
|
<div id='loading'>Loading...</div>
|
|
20
|
-
<div id="rotatingC" class="r2" style="width:
|
|
21
|
-
height:
|
|
21
|
+
<div id="rotatingC" class="r2" style="width: 50px;
|
|
22
|
+
height: 50px;
|
|
22
23
|
border: 1px solid red;
|
|
23
24
|
text-align: center; " >
|
|
24
25
|
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
json.id @newsvideo.id.to_s
|
|
3
|
+
json.generate_url api_newsvideo_generate_url(@newsvideo, { api_key: Wco::Setting.get('WASYACO_SIMPLE_API_KEY'),
|
|
4
|
+
api_secret: Wco::Setting.get('WASYACO_SIMPLE_API_SECRET') })
|
|
5
|
+
json.newspartials @newsvideo.newspartials.each do |newspartial|
|
|
6
|
+
json.generate_speech_url api_newspartial_generate_speech_url({ id: newspartial.id.to_s,
|
|
7
|
+
api_key: Wco::Setting.get('WASYACO_SIMPLE_API_KEY'),
|
|
8
|
+
api_secret: Wco::Setting.get('WASYACO_SIMPLE_API_SECRET'), })
|
|
9
|
+
json.generate_video_url api_newsproducer_studio_1_url({ newspartial_id: newspartial.id.to_s,
|
|
10
|
+
wco_origin: request.base_url,
|
|
11
|
+
api_key: Wco::Setting.get('WASYACO_SIMPLE_API_KEY'),
|
|
12
|
+
api_secret: Wco::Setting.get('WASYACO_SIMPLE_API_SECRET'), })
|
|
13
|
+
end
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
.full-text
|
|
16
16
|
.header.collapse-expand{ id: newspartial.id.to_s }
|
|
17
|
-
|
|
17
|
+
newspartial::#{newspartial.slug}
|
|
18
18
|
= link_to '[~]', edit_newspartial_path(newspartial)
|
|
19
19
|
%span{ class: 'gray' } #{newspartial.id}
|
|
20
|
-
= link_to '[
|
|
20
|
+
= link_to '[config.json]', api_newspartial_config_path(newspartial, format: :json, api_key: Wco::Setting.get('WASYACO_SIMPLE_API_KEY'), api_secret: Wco::Setting.get('WASYACO_SIMPLE_API_SECRET') ), target: :_blank
|
|
21
21
|
|
|
22
22
|
.full-textC
|
|
23
23
|
.flex-row
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
-# = button_to 'Generate video', newspartial_generate_video_path(newspartial), :data => { :confirm => 'Are you sure?' }
|
|
30
30
|
-# .small.gray ISHLIB3JS_ROOT
|
|
31
31
|
|
|
32
|
-
= link_to 'Generate video 2',
|
|
32
|
+
= link_to 'Generate video 2', api_newsproducer_studio_1_path({ newspartial_id: newspartial.id.to_s, wco_origin: request.base_url, api_key: Wco::Setting.get('WASYACO_SIMPLE_API_KEY'), api_secret: Wco::Setting.get('WASYACO_SIMPLE_API_SECRET') }), target: :_blank, class: 'btn btn-primary', data: { confirm: 'Are you sure?' }
|
|
33
33
|
|
|
34
34
|
Video:
|
|
35
35
|
- if newspartial.video
|
|
@@ -12,12 +12,21 @@
|
|
|
12
12
|
= f.text_field :slug, class: 'w-100'
|
|
13
13
|
|
|
14
14
|
.row
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
.a
|
|
16
|
+
.field
|
|
17
|
+
%label w_px
|
|
18
|
+
= f.text_field :w_px
|
|
19
|
+
.a
|
|
20
|
+
.field
|
|
21
|
+
%label h_px
|
|
22
|
+
= f.text_field :h_px
|
|
23
|
+
.descr
|
|
24
|
+
%ul
|
|
25
|
+
%li 1280x720 16:9
|
|
26
|
+
%li 1024x768 4:3
|
|
27
|
+
%li 854x480 16:9
|
|
28
|
+
%li 640x360 16:9
|
|
29
|
+
%li 640x480 4:3
|
|
21
30
|
|
|
22
31
|
.field
|
|
23
32
|
%label Body
|
|
@@ -28,5 +37,9 @@
|
|
|
28
37
|
-# = render '/wco/tags/index', tags: newsvideo.tags
|
|
29
38
|
= f.select :tag_ids, options_for_select(@tags_list, selected: newsvideo.tag_ids), {}, { multiple: true, class: 'select2' }
|
|
30
39
|
|
|
40
|
+
.field
|
|
41
|
+
%label next_overlay_ms
|
|
42
|
+
= f.text_field :next_overlay_ms
|
|
43
|
+
|
|
31
44
|
.actions
|
|
32
45
|
= f.submit
|
|
@@ -4,17 +4,24 @@
|
|
|
4
4
|
Newsvideo `#{@newsvideo.title}`
|
|
5
5
|
#{link_to '[~]', edit_newsvideo_path(@newsvideo)}
|
|
6
6
|
|
|
7
|
+
= link_to '_[config.json]', api_newsvideo_path(@newsvideo.id, { api_key: Wco::Setting.get('WASYACO_SIMPLE_API_KEY'), api_secret: Wco::Setting.get('WASYACO_SIMPLE_API_SECRET') }), target: :_blank
|
|
7
8
|
= link_to '[+ newspartial]', new_newspartial_path(newsvideo_id: @newsvideo.id)
|
|
8
|
-
= link_to '[search illustration]', pexels_search_path(newsvideo_id: @newsvideo.id), target: :_blank
|
|
9
|
+
= link_to '_[search illustration]', pexels_search_path(newsvideo_id: @newsvideo.id), target: :_blank
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
%ul.actions
|
|
13
|
+
%li #{@newsvideo.w_px} x #{@newsvideo.h_px}
|
|
12
14
|
%li
|
|
13
15
|
.d-inline-block= button_to 'split', split_newsvideo_path(@newsvideo), :data => { :confirm => 'Are you sure?' }
|
|
14
16
|
.small.gray
|
|
15
17
|
Uses sentences_to_phrases to reasonably create Wco::Newspartial's
|
|
16
18
|
%li
|
|
17
|
-
.d-inline-block= button_to 'generate',
|
|
19
|
+
.d-inline-block= button_to 'generate all audio', newsvideo_generate_all_audio_path(@newsvideo), :data => { :confirm => 'Are you sure?' }
|
|
20
|
+
%li
|
|
21
|
+
.d-inline-block= button_to 'generate (obsolete)', generate_newsvideo_path(@newsvideo), :data => { :confirm => 'Are you sure?' }
|
|
22
|
+
%li
|
|
23
|
+
.d-inline-block= button_to 'generate video & output', newsvideo_generate_all_video_path(@newsvideo), :data => { :confirm => 'Are you sure?' }
|
|
24
|
+
|
|
18
25
|
|
|
19
26
|
%i.fa.fa-compress.collapse-expand{ id: @newsvideo.id.to_s } Descr
|
|
20
27
|
.descr= raw @newsvideo.body.gsub(/(\r?\n){2}/, "<br /><br />")
|
data/config/routes.rb
CHANGED
|
@@ -15,9 +15,17 @@ Wco::Engine.routes.draw do
|
|
|
15
15
|
|
|
16
16
|
post 'reports', to: 'reports#create'
|
|
17
17
|
patch 'reports/:id/add-config', to: 'reports#add_config'
|
|
18
|
-
get 'newspartials/:id/config',
|
|
18
|
+
get 'newspartials/:id/config', to: 'newspartials#show_config', as: :newspartial_config
|
|
19
|
+
match 'newspartials/:id/generate-speech', to: 'newspartials#generate_speech', as: :newspartial_generate_speech, via: [ :get, :post ]
|
|
20
|
+
|
|
21
|
+
get 'newsproducer/canvas', to: 'newsproducer#canvas'
|
|
22
|
+
get 'newsproducer/canvas_minimal', to: 'newsproducer#canvas_minimal'
|
|
23
|
+
get 'newsproducer/studio_1', to: 'newsproducer#studio_1'
|
|
24
|
+
|
|
19
25
|
|
|
20
26
|
match 'newsvideos/:id/generate-illustration', to: 'newsvideos#generate_illustration', as: :newsvideo_generate_illustration, via: [ :get, :post ]
|
|
27
|
+
match 'newsvideos/:id/generate-video', to: 'newsvideos#generate', as: :newsvideo_generate, via: [ :get, :post ]
|
|
28
|
+
get 'newsvideos/:id', to: 'newsvideos#show', as: :newsvideo, defaults: { format: :json }
|
|
21
29
|
|
|
22
30
|
get 'tags', to: 'tags#index'
|
|
23
31
|
|
|
@@ -69,13 +77,13 @@ Wco::Engine.routes.draw do
|
|
|
69
77
|
resources :newspartials
|
|
70
78
|
|
|
71
79
|
|
|
72
|
-
get 'newsproducer/canvas', to: 'newsproducer#canvas'
|
|
73
|
-
get 'newsproducer/canvas_minimal', to: 'newsproducer#canvas_minimal'
|
|
74
|
-
get 'newsproducer/studio_1', to: 'newsproducer#studio_1'
|
|
75
80
|
|
|
76
81
|
match 'newsvideos/:id/generate-illustration', to: 'newsvideos#generate_illustration', as: :newsvideo_generate_illustration, via: [ :get, :post ]
|
|
82
|
+
match 'newsvideos/:id/generate-all-audio', to: 'newsvideos#generate_all_audio', as: :newsvideo_generate_all_audio, via: [ :get, :post ]
|
|
83
|
+
match 'newsvideos/:id/generate-all-video', to: 'newsvideos#generate_all_video', as: :newsvideo_generate_all_video, via: [ :get, :post ]
|
|
77
84
|
post 'newsvideos/:id/generate', to: 'newsvideos#generate', as: :generate_newsvideo
|
|
78
85
|
post 'newsvideos/:id/split', to: 'newsvideos#split', as: :split_newsvideo
|
|
86
|
+
post 'newsvideos/:id/add-image-as-overlay', to: 'newsvideos#add_image_as_overlay'
|
|
79
87
|
resources :newsvideos
|
|
80
88
|
|
|
81
89
|
resources :obfuscated_redirects
|