Feature request/doc request : Play all segments of a given speaker
PaulLerner opened this issue · 18 comments
Hi,
I'd like the "play" button of a given speaker in the "Segment Labeling" section to play all the segments of that speaker in a given order.
I should be able to implement it myself but I'm having problems diving into the code given the lack of technical documentation.
Bests,
Hi,
You can do it in this way:
- First, filter the regions with given speaker - you can do it with
iterateRegions
function, any region has a speaker param inside - Subscribe those regions to
out
event (wavesurfer regions doc) - Start playback from first region in filtered regions, and on
out
event move a playback to next region
I don't think this is the best solution, but i doesn't see others now
Hi, thank you for your answer,
I'm having trouble with associating a function to to that play button. I've created a playSpeaker()
function in the MainController
class in app/controller.js
. So I changed ng-click="playStop()"
to ng-click="ctrl.playSpeaker()"
but it doesn't have any effect (for now the function just logs a debug message). It's strange as any other change I make on app/controller.js
code or app/playPartDirective.js
is effective.
ng-click="playStop()"
relates to app/playPartDirective.js
so you need to add playSpeaker()
function to playPartDirective
, not to MainController, and use it without ctrl.
so it will be used like ng-click="playSpeaker()"
- we don't use a controller-as syntax in this directive
Ok so I replaced playStop
by playSpeaker
using the same syntax:
scope.playSpeaker = function (){
console.log("in playSpeaker function ");
var ctrl = scope.$parent.ctrl;
var speaker_id=scope.$parent.speaker;
console.log("speaker_id",speaker_id);
ctrl.iterateRegions(function (region) {
let current_speaker = region.data.speaker;
if (current_speaker[0]==speaker_id){
console.log("region of the same speaker:",region);
region.on('out', function(e) {
console.log("logging ",region," on out event");
scope.rep.start=region.start;
scope.rep.end=region.end;
});
}
});
scope.isPlaying ? stop() : play();
I'm not sure this is what you thought about but anyway I noticed a problem with the playStop
function (i.e. the above function last line):
- It doesn't work unless you first click somewhere
- It behaves in a similary way as
ctrl.playRegion()
: no matter which speaker I click on, it only plays the currently selected region. - Only difference with
ctrl.playRegion()
I can see is that the cursor does not move so the 'out' event is never triggered.
Hi Paul. Please try following code
scope.playSpeaker = function () {
console.log("in playSpeaker function ");
var ctrl = scope.$parent.ctrl;
var speaker_id=scope.$parent.speaker;
console.log("speaker_id",speaker_id);
let firstRegion = null
ctrl.iterateRegions(function (region) {
let current_speaker = region.data.speaker;
if (current_speaker[0]==speaker_id){
if (!firstRegion) {
firstRegion = region
region.play()
}
console.log("region of the same speaker:",region);
region.on('out', function(e) {
console.log("logging ",region," on out event");
});
}
});
}
For now, it will plays a first region of selected speaker. You can catch 'out' event and play a next region. If you need more info, please lmk. Thanks
Hi, thank you for your answer.
The 'out' event doesn't fire sometime, I've read about a similar issue here
So when the region is done playing I have to use the ctrl.playPause()
button. However, using this ctrl.playPause()
button I almost have the behaviour I want after playing the next region (stored in a list) in the 'out' event as this :
scope.playSpeaker = function () {
console.log("in playSpeaker function ");
var ctrl = scope.$parent.ctrl;
var speaker_id=scope.$parent.speaker;
console.log("speaker_id",speaker_id);
let firstRegion = null
var speakers_regions=[]
var i =0
ctrl.iterateRegions(function (region) {
let current_speaker = region.data.speaker;
if (current_speaker[0]==speaker_id){
if (!firstRegion) {
firstRegion = region
region.play()
}
speakers_regions.push(region)
region.on('out', function(e) {
i+=1;
console.log(i);
speakers_regions[i].play()
console.log("logging ",region," on out event");
});
}
});
}
What's the difference between region.on('out'
and source.addEventListener('out'
?
Hi, thank you for your answer.
The 'out' event doesn't fire sometime, I've read about a similar issue hereSo when the region is done playing I have to use the
ctrl.playPause()
button. However, using thisctrl.playPause()
button I almost have the behaviour I want after playing the next region (stored in a list) in the 'out' event as this :scope.playSpeaker = function () { console.log("in playSpeaker function "); var ctrl = scope.$parent.ctrl; var speaker_id=scope.$parent.speaker; console.log("speaker_id",speaker_id); let firstRegion = null var speakers_regions=[] var i =0 ctrl.iterateRegions(function (region) { let current_speaker = region.data.speaker; if (current_speaker[0]==speaker_id){ if (!firstRegion) { firstRegion = region region.play() } speakers_regions.push(region) region.on('out', function(e) { i+=1; console.log(i); speakers_regions[i].play() console.log("logging ",region," on out event"); }); } }); }What's the difference between
region.on('out'
andsource.addEventListener('out'
?
Hi Paul
source
here is a AudioBufferSourceNode
, and it has only ended
event listener (doc)
Hi,
Thanks for the clarification. I was still not able to solve that out event that doesn't fire though, have you looked into the similar issue on wavesurfer git ?
I have a similar issue where I want to play a region in loop, I've modified the playRegion
like this:
playRegion() {
if (this.selectedRegion) {
this.selectedRegion.play();
var region= this.selectedRegion;
region.on('out', function(e) {
region.play();
console.log("logging ",region," on out event");
});
}
// play silence region
else {
var silence = this.calcSilenceRegion();
this.wavesurfer.play(silence.start, silence.end);
}
}
But it behaves the same was I've described above : the 'out' event doesn't fire unless I press the play button manually.
Hi Paul
I can't reproduce it on my machine
Please, give me a sample data (regions & audio file), or you have this issue on demo regions and audio?
I have this issue on demo regions and audio...
What happens on your machine ?
I'm running on ubuntu 16.04
with npm 6.11.3
and node v12.11.1
running npm install
gives me :
npm WARN speech-recognition@1.0.0 No repository field.
npm WARN speech-recognition@1.0.0 scripts['server'] should probably be scripts['start'].
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 15927 packages in 10.604s
found 0 vulnerabilities
Hi Paul
On my machine (Ubuntu 18.04
, npm 6.13.0
and node v9.6.1
) i have a next:
npm WARN speech-recognition@1.0.0 No repository field.
npm WARN speech-recognition@1.0.0 scripts['server'] should probably be scripts['start'].
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
added 1063 packages from 536 contributors and audited 15927 packages in 37.103s
Ok so the warnings look similar.
Have you tried the above code in your machine ?
Does the 'out' event fires consistently ?
Bests,
Hi Paul
Sorry for a long answer
I get this bug too and found a solution, the code above can be used a start point for play all regions of selected speaker:
scope.speakerRegions = []
const playRegion = (currentRegion, nextRegionIndex) => {
currentRegion.on('out', null)
if (nextRegionIndex < scope.speakerRegions.length - 1) {
const nextRegion = scope.speakerRegions[nextRegionIndex]
nextRegion.on('out', () => playRegion(nextRegion, nextRegionIndex + 1))
seek(nextRegion.start)
}
}
const seek = (time) => {
scope.wavesurfer.seekTo((time) / scope.wavesurfer.getDuration());
}
function play() {
console.log('play', scope.wavesurfer)
console.log("in playSpeaker function ");
var ctrl = scope.$parent.ctrl;
var speaker_id=scope.$parent.speaker;
console.log("speaker_id",speaker_id);
ctrl.iterateRegions(function (region) {
let current_speaker = region.data.speaker;
if (current_speaker[0] === speaker_id) {
scope.speakerRegions.push(region)
}
});
scope.speakerRegions[0].on('out', () => playRegion(scope.speakerRegions[0], 1))
scope.wavesurfer.play()
}
You need to pass a wavesurfer from main controller, i.e. :
<play-speaker wavesurfer="ctrl.wavesurfer"></play-speaker>
We can't use a region play
method, because it stops before an out
event. When i tested it previous time, looks like i make a mistake, sorry.
Hi, thank you for your answer.
I'm sorry but some things are unclear to me: where do I put all of this code ? In playPartDirective ?
The function play in there looks very different...
Also before we were talking about implementing the function as scope.playSpeaker = function () {}
not as function playSpeaker() {}
I don't understand what you mean by
You need to pass a wavesurfer from main controller, i.e. :
<play-speaker wavesurfer="ctrl.wavesurfer"></play-speaker>
Currently, the button is located in playPart and is like
<button class="btn btn-primary btn-sm" ng-click="playFirstRegion()" style="vertical-align: top; height: 23px">
<i class="glyphicon glyphicon-play" ng-show="!isPlaying" style="vertical-align: top;"></i>
<i class="glyphicon glyphicon-pause" ng-show="isPlaying" style="vertical-align: top;"></i>
</button>
Hi Paul
Can you please give a link to your code (i mean an your fork), with your directive? I'll show where you will need to insert a code
re You need to pass a wavesurfer from main controller, i.e.
- you need to pass a wavesurfer instance into your directive, because you need a direct access to wavesurfer object - you'll need to use play() and seek() functions
Hi,
Here's the link to the current playFirstRegion
function : https://github.com/PaulLerner/gecko/blob/pyannote/app/playPartDirective.js#L99
(Don't mind the playSpeaker
and playStop
functions)
Thank you for your help :)
Hi Paul
Please check this patch, nvm re changes in config.js - i made it for our current regions format
Thanks !
It needed some tweaks but it works 😁