Sphinx 4 Transcription Time Index - cmusphinx

How do I get time index (or frame number) in Sphinx 4 when I set it to transcribe an audio file?
The code I'm using looks like this:
audioURL = ...
AudioFileDataSource dataSource = (AudioFileDataSource) cm.lookup("audioFileDataSource");
dataSource.setAudioFile(audioURL, null);
Result result;
while ((result = Recognizer.recognize()) != null) {
Token token = result.getBestToken();
//DoubleData data = (DoubleData) token.getData();
//long frameNum = data.getFirstSampleNumber(); // data seem always null
String resultText = token.getWordPath(false, false);
...
}
I tried to get time of transcription from result/token objects, e.g. similar to what a subtitler do. I've found Result.getFrameNumber() and Token.getFrameNumber() but they appear to return the number of frames decoded and not the time (or frame) where the result was found in the context of entire audio file.
I looked at AudioFileDataSource.getDuration()[=private] and the Recognizer classes but haven't figure out how to get the needed transcribed time-index..
Ideas? :)

Frame number is the time multiplied by frame rate which is 100 frames/second.
Anyway, please find the patch for subtitles demo which returns timings here:
http://sourceforge.net/mailarchive/forum.php?thread_name=1380033926.26218.12.camel%40localhost.localdomain&forum_name=cmusphinx-devel
The patch applies to subversion trunk, not to the 1.0-beta version.
Please note that this part is under major refactoring, so the API will be obsolete soon. However, I hope you will be able to create subtitles with just few calls without all current complexity.

Related

Fastest way to slice and download hundreds of NetCDF files from THREDDS/OPeNDap server

I am working with NASA-NEX-GDDP CMIP6 data. I currently have working code that individually opens and slices each file, however it takes days to download one variable for all model outputs and scenarios. My goal is to have all temperature and precipitation data for all models outputs and scenarios then apply climate indicators and make an ensemble with xclim.
url = 'https://ds.nccs.nasa.gov/thredds2/dodsC/AMES/NEX/GDDP-CMIP6/UKESM1-0-LL/ssp585/r1i1p1f2/tasmax/tasmax_day_UKESM1-0-LL_ssp585_r1i1p1f2_gn_2098.nc'
lat = 53
lon = 0
try:
with xr.open_dataset(url) as ds:
ds.interp(lat=lat,lon=lon).to_netcdf(url.split('/')[-1])
except Exception as e: print(e)
This code works but is very slow (days for one variable, one location). Wondering if there is a better, faster way? I'd rather not download the whole files as they are each 240 MB!
Update:
I have also tried the following to take advantage of dask parallel tasks and it is slightly faster but still on the order of days to complete for a full variable output:
def interp_one_url(path,lat,lon):
with xr.open_dataset(path) as ds:
ds = ds.interp(lat=lat,lon=lon)
return ds
urls = ['https://ds.nccs.nasa.gov/thredds2/dodsC/AMES/NEX/GDDP-CMIP6/UKESM1-0-LL/ssp585/r1i1p1f2/tasmax/tasmax_day_UKESM1-0-LL_ssp585_r1i1p1f2_gn_2100.nc',
'https://ds.nccs.nasa.gov/thredds2/dodsC/AMES/NEX/GDDP-CMIP6/UKESM1-0-LL/ssp585/r1i1p1f2/tasmax/tasmax_day_UKESM1-0-LL_ssp585_r1i1p1f2_gn_2099.nc']
lat = 53
lon = 0
paths = [url.split('/')[-1] for url in urls]
datasets = [interp_one_url(url,lat,lon) for url in urls]
xr.save_mfdataset(datasets, paths=paths)
One way is to download via the ncss portal instead of the OpenDAP, available via NASA. The URL is different but it is iterative as well.
e.g.
lat = 53
lon = 0
URL = "https://ds.nccs.nasa.gov/thredds/ncss/AMES/NEX/GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/pr/pr_day_ACCESS-CM2_historical_r1i1p1f1_gn_2014.nc?var=pr&north={}&west={}&east={}&south={}&disableProjSubset=on&horizStride=1&time_start=2014-01-01T12%3A00%3A00Z&time_end=2014-12-31T12%3A00%3A00Z&timeStride=1&addLatLon=true"
wget.download(URL.format(lat,lon,lon+1,lat-1) #north, west, east, south boundary
This accomplishes the slicing and download in one step. Once you have the URL, you can use something like wget, and complete downloads in parallel, which will speed up compared to selecting and saving one at a time

Alexa Audio Player Directive - Speak After Audio Played

I am trying to make an Alexa fitness app and when the user begins an exercise, Alexa explains the exercise and then plays an audio file. I would like to then get Alexa to explain the second exercise and play the next audio file. Repeating this for around 5 exercises.
Here is part of my code:
else if (slotValues.area.heardAs == 'lower body' || slotValues.area.heardAs == 'lower' || slotValues.area.heardAs == 'legs') {
say = 'Great choice! We will get started with an lower body workout. Let\'s begin with a warm-up. The first exercise is ' + lowerWorkout1[0].name + lowerWorkout1[0].description + ' 3. 2. 1.' ;
handlerInput.responseBuilder.addAudioPlayerPlayDirective('REPLACE_ALL', sLowerWorkout1.url, sLowerWorkout1.token, 0, null, sLowerWorkout1.metadata);
// Then explain second exercise
// Play the second audio
// Then explain third exercise
// Play the third audio
}
/.../
return responseBuilder
.speak(say)
//.reprompt('try again, ' + say)
.getResponse();
I have tried to add the a second say variable after the audioPlayerPlayDirective but it only outputs the second .speak() and then plays the first audio file. I have also tried to add another .speak() after getResponse() but that gives me an error.
Does anyone have any ideas as to how I can do this?
Thanks,
Martin
Once your audio player starts, your skill ends its session. Meaning either you are playing mp3s, either you are in skill session and you can speak. Not both.
I guess workaround would be to have all as audio clips.

Calculate time differences in nodejs from a manually created format

I wanted to calculate the time differences (in minutes). However the data I gotten is not using a conventional time format, it is using the following format "yyyy-mm-dd-HH-MM-ss" in UTC time. I can't use this directly in moments or other library as seems. What is the recommendations to handle this specific format?
How can I use library such as "moment" to calculate the time differences with this time format from my data?
Not sure but possibly try it with moment, something like:
const moment = require('moment');
const yourSpecialFormat = 'YYYY-MM-DD-HH-mm-ss';
const someDateInYourFormat = '2020-02-22-05-58-57';
let now = moment(moment().format(yourSpecialFormat), yourSpecialFormat);
let then = moment(someDateInYourFormat, yourSpecialFormat);
console.log('Hours ----> ', moment.duration(now.diff(then)).asHours());
console.log('Minutes ----> ', moment.duration(now.diff(then)).asMinutes ());

Python Pandas data frame setting copy of slice working sometimes but not always, despite nearly identical code

I have one data frame called patient_df that is made like this:
PATIENT_COLS = ['Origin', 'Status', 'Team', 'Bed', 'Admit_Time', 'First_Consult', 'Decant_Time', 'Ward_Time', 'Discharge_Order', 'Discharged'] # data to track for each patient
patient_df = pd.DataFrame(columns=PATIENT_COLS)
Then, at multiple points in my code I will access a row of this data frame and update fields associated with it (the row at patient_ID doesn't exist prior to me creating it in the first line):
patient_df.loc[patient_ID] = [None for i in range(NUM_PATIENT_COLS)]
record = patient_df.loc[patient_ID]
record.Origin = ORIGIN()
record.Admit_Time = sim_time
This code runs perfectly with no errors or warnings and the output is as expected (the actual data frame is updated).
However, I have another data frame called ip_df:
ip_df = pd.read_csv(PATH + 'Clean_IP.csv')
Now, when I try to access the rows in the same way (this time the rows already exist):
for patient in ALC_patients:
record = ip_df.loc[patient]
orig_end = record.IP_Discharge_DT
record.IP_LOS = MAX_STAY
record.IP_Discharge_DT = record.N_Left_DT + timedelta(days=MAX_STAY)
I get
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
Now, I realize what's happening is I'm actually accessing a copy of the data frame and thus not updating the actual one, and I can fix this by using
ip_df[patient, 'IP_LOS'] = MAX_STAY
However, I find the first code much cleaner, plus I don't have to make the data frame search for the row again every time. Why is this working with patient_df but not for ip_df, and is there anything I can change to use code more like what I am for patient_df?
pd.options.mode.chained_assignment = None # default='warn'
According to this link setting this in your code will turn off the warn flag

OpenCV - Capture arbitrary frame from video file

I use the following code to extract a specific frame from a video file. In this example, I'm simply getting the middle frame:
import cv2
video_path = '/tmp/wonderwall.mp4'
vidcap = cv2.VideoCapture(video_path)
middle_frame = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT) / 2)
success, image = vidcap.read()
count = 0
success = True
while success:
success, image = vidcap.read()
if count == middle_frame:
temp_file = tempfile.NamedTemporaryFile(suffix='.jpg', delete=False)
cv2.imwrite(temp_file.name, image)
count += 1
However, with this method, capturing the middle frame in a very large file can take a while.
Apparently, in the older cv module, one could do:
import cv
img = cv.QueryFrame(capture)
Is there a similar way in cv2 to grab a specific frame in a video file, without having to iterate through all frames?
You can do it in the same way, in C++ (python conversion should be more than easy).
cv::VideoCapture cap("file.avi");
double number_of_frame = cap.get(CV_CAP_PROP_FRAME_COUNT);
cap.set(CV_CAP_PROP_POS_FRAMES, IndexOfTheFrameYouWant);
cv::Mat frameIwant = cap.read();
For reference :
VideoCapture::get(int propId)
Can take various flag returning nearly all you can wish for (http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html and look for get() ).
VideoCapture::set(int propId, double value)
Set will do what you want (same doc look for set) if you use the propID 1, and the index of the frame you desire.
You should note that if the index you use as parameter is superior to the max frame that the code will grab the last frame of the video if you are lucky, or crash at run time.

Resources