We want to have notifications that can be sent to the Console to simulate an external Event
Question:
We want to have notifications that can be sent to the Console to simulate an external Event Logging System that may be used for Analytics and Live Monitoring.
- Implement Observer pattern being the Recording class, the Observable Subject, and a new Notifier class, the Observer.
- The event should be triggered when the Recording is updated with the transcript (or result from the closed captioning process) and the message generated should include information from the recording itself.
Update the Main class accordingly.
package loggy;
import java.util.LinkedList; import java.util.List; import java.util.UUID;
/** * @author jesus * */ public class Main {
/** * @param args */ public static void main(String[] args) { int maxmockups = 1; // The number of mock-ups to be generated.
List recordings = new LinkedList(); // Set the mock-up recordings. for (int i = 0; i < maxmockups; i++) { String fileName = "recording-" + String.valueOf(i) + ".mp4"; Long fileSize = (long) (Math.random() * (1024L - 1L)); recordings.add(new Recording(UUID.randomUUID(), fileName, fileSize)); }
// Enqueue recordings for closed captioning. CCSpooler spooler = new CCSpooler(); recordings.forEach((recording) -> { spooler.enqueue(recording); }); spooler.shutdown(); }
}
package loggy;
import java.util.UUID;
/** * @author jesus * */ public class Recording { private UUID uuid; private String fileName; private Long fileSize; private String mediaFileMock; private String ccFileMock;
/** * @return the fileName */ public String getFileName() { return fileName; }
/** * @param fileName the fileName to set */ public void setFileName(String fileName) { this.fileName = fileName; }
/** * @return the fileSize */ public Long getFileSize() { return fileSize; }
/** * @param fileSize the fileSize to set */ public void setFileSize(Long fileSize) { this.fileSize = fileSize; }
public String getMediaFileMock() { return mediaFileMock; }
public void setMediaFileMock(String mediaFileMock) { this.mediaFileMock = mediaFileMock; }
public String getCcFileMock() { return ccFileMock; }
public void setCcFileMock(String ccFileMock) { this.ccFileMock = ccFileMock; }
/** * @param uuid * @param fileName * @param fileSize */ public Recording(UUID uuid, String fileName, Long fileSize) { super(); this.uuid = uuid; this.fileName = fileName; this.fileSize = fileSize; this.mediaFileMock = fileName; }
}
package loggy;
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
/** * @author jesus * */ public class CCSpooler { private final ExecutorService executor;
public CCSpooler() { // creating a pool of 5 threads this.executor = Executors.newFixedThreadPool(5); }
public void enqueue(Recording recording) { Runnable worker = new CCWorker(recording); // calling execute method of ExecutorService executor.execute(worker); }
public void shutdown() { executor.shutdown(); while (!executor.isTerminated()) { } System.out.println("Finished all threads"); } }
package loggy;
import aws.api.AWSTranscribeAPI; import google.api.GoogleSpeech2TextAPI;
/** * @author jesus * */ public class CCWorker implements Runnable { private final Recording recording;
// Constructor to assign a message when creating a new thread public CCWorker(Recording recording) { this.recording = recording; }
@Override /** * */ public void run() { System.out.println( Thread.currentThread().getName() + " (Start closed captioning) recording = " + recording.getFileName()); // Trigger CC using the local methods. triggerGoogleClosedCaptioning(); triggerAWSClosedCaptioning();
// Trigger CC using the adapter methods. // TODO
System.out.println(Thread.currentThread().getName() + " (End closed captioning)"); }
private void triggerGoogleClosedCaptioning() { String rawFile = recording.getMediaFileMock(); Long fileSize = recording.getFileSize(); GoogleSpeech2TextAPI api = new GoogleSpeech2TextAPI(); String ccFile = ""; System.out.println("Closed captioning " + rawFile + " will take " + fileSize + " milliseconds..."); try { // Simulate the delay. Thread.sleep(fileSize); // MockUp transcript process. String speechClient = api.instantiateClient(); String audioBytes = api.fileToMemory(rawFile); String config = api.buildSyncRecognizeRequestConfig(); String audio = api.buildSyncRecognizeRequestAudio(); api.performSpeechRecognition(config, audio); String transcript = api.getFirstTranscriptAlternative(); ccFile = transcript; } catch (InterruptedException e) { e.printStackTrace(); } recording.setCcFileMock(ccFile); System.out.println(ccFile + " processed using GoogleSpeech2TextAPI"); } private void triggerAWSClosedCaptioning() { String rawFile = recording.getMediaFileMock(); Long fileSize = recording.getFileSize(); AWSTranscribeAPI api = new AWSTranscribeAPI(); String ccFile = ""; System.out.println("Closed captioning " + rawFile + " will take " + fileSize + " milliseconds..."); try { // Simulate the delay. Thread.sleep(fileSize); // MockUp transcript process. String client = api.clientCreate(); String stream = api.getStreamFromFile(rawFile); api.startStreamTranscription(client, stream); String transcript = api.getResult(); api.clientClose(client); ccFile = transcript; } catch (InterruptedException e) { e.printStackTrace(); } recording.setCcFileMock(ccFile); System.out.println(ccFile + " processed using AWSTranscribeAPI"); }
}
package google.api;
import java.util.ArrayList; import java.util.List;
/* This is a very rough and ugly Google Speech2Text API pretender * for academic purposes non related to API programming nor Speech2Text * recognition or whatsoever. * * But if you are curious on how the transcripts are actually done using * Google API you can see a real example at: * https://cloud.google.com/speech-to-text/docs/libraries#client-libraries-resources-java */ public class GoogleSpeech2TextAPI {
List transcriptAlternatives; String fileName;
public GoogleSpeech2TextAPI() { transcriptAlternatives = new ArrayList(); }
public String instantiateClient() { return "speechClient"; }
public String fileToMemory(String fileName) { this.fileName = fileName; return "audioBytes"; }
public String buildSyncRecognizeRequestConfig() { return "config"; }
public String buildSyncRecognizeRequestAudio() { return "audio"; }
public void performSpeechRecognition(String config, String audio) { // Mock-up results. System.out.println("Performing Speech Recognition based on " + config + " for " + audio); transcriptAlternatives.add(""); transcriptAlternatives.add(""); }
public String getFirstTranscriptAlternative() { for (String result : transcriptAlternatives) { // Returns the first element. System.out.println("Returning " + result); return result + " for " + this.fileName; } return null; }
public List getResultList() { return transcriptAlternatives; } public String recognitionAudio( ) { return null; } public void setRecognitionConfigParameters() { System.out.println("Set parameters"); } }
package aws.api;
import java.util.ArrayList; import java.util.List;
/* This is a very rough and ugly AWS Transcribe API pretender * for academic purposes non related to API programming nor Speech2Text * recognition or whatsoever. * * But if you are curious on how the transcripts are actually done using * AWS API you can find real examples at: * https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/example_code/transcribe */ public class AWSTranscribeAPI {
List transcript; String fileName;
public AWSTranscribeAPI() { transcript = new ArrayList(); }
public String getStreamFromFile(String audioFileName) { this.fileName = audioFileName; return "streamFromFile"; }
public void startStreamTranscription(String client, String stream) { System.out.println(client + " is starting streaming " + stream); transcript.add(" for " + this.fileName); for (int i = 1; i <= 5; i++) { transcript.add("line-" + i); } }
public String getResult() { String transcriptString = "";
for (String s : transcript) { transcriptString += s + "t"; } return transcriptString; }
public String clientCreate() { return "client"; }
public void clientClose(String client) { System.out.println("Closing " + client); } }
Statistical Reasoning for Everyday Life
ISBN: 978-0321817624
4th edition
Authors: Jeff Bennett, Bill Briggs, Mario F. Triola