package io.lumify.core.ingest.video; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; public class VideoTranscript implements Serializable { private SortedSet<TimedText> entries = new TreeSet<TimedText>(); public VideoTranscript() { } public VideoTranscript(JSONObject json) { try { JSONArray entriesJson = (JSONArray) json.get("entries"); for (int i = 0; i < entriesJson.length(); i++) { JSONObject entryJson = (JSONObject) entriesJson.get(i); entries.add(new TimedText(entryJson)); } } catch (JSONException e) { throw new RuntimeException("Could not parse video transcript JSON", e); } } public List<TimedText> getEntries() { return new ArrayList<TimedText>(entries); } public void add(Time time, String text) { entries.add(new TimedText(time, text)); } public VideoTranscript merge(VideoTranscript videoTranscript) { for (TimedText entry : videoTranscript.entries) { entries.add(entry); } return this; } public static VideoTranscript merge(VideoTranscript a, VideoTranscript b) { VideoTranscript result = new VideoTranscript(); if (a != null) { result.merge(a); } if (b != null) { result.merge(b); } return result; } public JSONObject toJson() { try { JSONObject result = new JSONObject(); JSONArray entriesJson = new JSONArray(); for (TimedText entry : entries) { entriesJson.put(entry.toJson()); } result.put("entries", entriesJson); return result; } catch (JSONException e) { throw new RuntimeException("Could not create JSON", e); } } @Override public String toString() { StringBuilder result = new StringBuilder(); for (TimedText entry : entries) { result.append(entry.getTime().toString()); result.append("\n"); result.append(entry.getText()); result.append("\n"); } return result.toString(); } public long getDuration() { if (getEntries().size() > 0) { long start = getEntries().get(0).getTime().getStart(); long end = getEntries().get(getEntries().size() - 1).getTime().getEnd(); return end - start; } return 0; } public Integer findEntryIndexFromStartTime(long frameStartTime) { int entryIndex = 0; for (TimedText entry : getEntries()) { if (entry.getTime().getStart() == frameStartTime) { return entryIndex; } entryIndex++; } return null; } public static class TimedText implements Comparable<TimedText>, Serializable { private Time time; private String text; public TimedText(Time time, String text) { this.time = time; this.text = text; } public TimedText(JSONObject json) { try { Long start = null; Long end = null; if (json.has("start")) { start = json.getLong("start"); } if (json.has("end")) { end = json.getLong("end"); } this.time = new Time(start, end); this.text = json.getString("text"); } catch (JSONException e) { throw new RuntimeException("Could not parse TimedText JSON", e); } } public Time getTime() { return time; } public String getText() { return text; } public JSONObject toJson() { try { JSONObject result = new JSONObject(); if (getTime().getStart() != null) { result.put("start", getTime().getStart().longValue()); } if (getTime().getEnd() != null) { result.put("end", getTime().getEnd().longValue()); } result.put("text", getText()); return result; } catch (JSONException e) { throw new RuntimeException(e); } } @Override public int compareTo(TimedText other) { Time time = getTime(); Time timeOther = other.getTime(); int result = time.getStart().compareTo(timeOther.getStart()); if (result != 0) { return result; } if (time.getEnd() == null && timeOther.getEnd() == null) { return 0; } if (time.getEnd() == null) { return -1; } if (timeOther.getEnd() == null) { return 1; } return time.getEnd().compareTo(timeOther.getEnd()); } } public static class Time implements Serializable { private Long start; private Long end; /** * @param start time in milliseconds * @param end time in milliseconds */ public Time(Long start, Long end) { this.start = start; this.end = end; } @Override public String toString() { return toString(start) + "-" + toString(end); } private String toString(Long t) { if (t == null) { return ""; } return String.format("%02d:%02d:%02d.%03d", t / 60 / 60 / 1000, (t / 60 / 1000) % 60, (t / 1000) % 60, t % 1000); } public Long getStart() { return start; } public Long getEnd() { return end; } } }