public static Transcript parse(String jsonStr) {
        try {
            Transcript transcript = new Transcript();
            long startTime = -1L;
            long endTime = -1L;
            long segmentStartTime = -1L;
            long segmentEndTime = -1L;
            long duration = 0L;
            String speaker = "";
            String prevSpeaker = "";
            String segmentBody = "";
            JSONArray objSegments;
            Set<String> speakers = new HashSet<>();

            try {
                JSONObject obj = new JSONObject(jsonStr);
                objSegments = obj.getJSONArray("segments");
            } catch (JSONException e) {
                e.printStackTrace();
                return null;
            }

            for (int i = 0; i < objSegments.length(); i++) {
                JSONObject jsonObject = objSegments.getJSONObject(i);
                segmentEndTime = endTime;
                startTime = Double.valueOf(jsonObject.optDouble("startTime", -1) * 1000L).longValue();
                endTime = Double.valueOf(jsonObject.optDouble("endTime", -1) * 1000L).longValue();
                if (startTime < 0 || endTime < 0) {
                    continue;
                }
                if (segmentStartTime == -1L) {
                    segmentStartTime = startTime;
                }
                duration += endTime - startTime;

                prevSpeaker = speaker;
                speaker = jsonObject.optString("speaker");
                speakers.add(speaker);
                if (StringUtils.isEmpty(speaker) && StringUtils.isNotEmpty(prevSpeaker)) {
                    speaker = prevSpeaker;
                }
                String body = jsonObject.optString("body");
                if (!prevSpeaker.equals(speaker)) {
                    if (StringUtils.isNotEmpty(segmentBody)) {
                        segmentBody = StringUtils.trim(segmentBody);
                        transcript.addSegment(new TranscriptSegment(segmentStartTime,
                                segmentEndTime,
                                segmentBody,
                                prevSpeaker));
                        segmentStartTime = startTime;
                        segmentBody = body.toString();
                        duration = 0L;
                        continue;
                    }
                }

                segmentBody += " " + body;

                if (duration >= TranscriptParser.MIN_SPAN) {
                    // Look ahead and make sure the next segment does not start with an alphanumeric character
                    if ((i + 1) < objSegments.length()) {
                        String nextSegmentFirstChar = objSegments.getJSONObject(i + 1)
                                .optString("body")
                                .substring(0, 1);
                        if (!StringUtils.isAlphanumeric(nextSegmentFirstChar)
                                && (duration < TranscriptParser.MAX_SPAN)) {
                            continue;
                        }
                    }
                    segmentBody = StringUtils.trim(segmentBody);
                    transcript.addSegment(new TranscriptSegment(segmentStartTime, endTime, segmentBody, speaker));
                    duration = 0L;
                    segmentBody = "";
                    segmentStartTime = -1L;
                }
            }

            if (!StringUtil.isBlank(segmentBody)) {
                segmentBody = StringUtils.trim(segmentBody);
                transcript.addSegment(new TranscriptSegment(segmentStartTime, endTime, segmentBody, speaker));
            }

            if (transcript.getSegmentCount() > 0) {
                transcript.setSpeakers(speakers);
                return transcript;
            } else {
                return null;
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
@Test
    public void testParse() {
        String type = "application/json";
        Transcript result = TranscriptParser.parse(jsonStr, type);
        // There isn't a segment at 900L, so go backwards and get the segment at 800L
        assertEquals(result.getSegmentAtTime(900L).getSpeaker(), "John Doe");
        assertEquals(result.getSegmentAtTime(930L).getWords(), "And");

        // blank string
        String blankStr = "";
        result = TranscriptParser.parse(blankStr, type);
        assertEquals(result, null);

        result = TranscriptParser.parse(null, type);
        assertEquals(result, null);

        // All blank lines
        String allNewlinesStr = "\r\n\r\n\r\n\r\n";
        result = TranscriptParser.parse(allNewlinesStr, type);
        assertEquals(result, null);

        // segments is missing
        String jsonStrBad1 = "{'version': '1.0.0', "
                + "'segmentsX': [ "
                + "{ 'speaker' : 'John Doe', 'startTime': 0.8, 'endTime': 1.9, 'body': 'And' },"
                + "{ 'startTime': 2.9, 'endTime': 3.4, 'body': 'the' },"
                + "{ 'startTime': 3.5, 'endTime': 3.6, 'body': 'person' }]}";
        result = TranscriptParser.parse(jsonStrBad1, type);
        assertEquals(result, null);

        // invalid time formatting
        String jsonStrBad2 = "{'version': '1.0.0', "
                + "'segments': [ "
                + "{ 'speaker' : 'XJohn Doe', 'startTime': stringTime, 'endTime': stringTime, 'body': 'And' },"
                + "{ 'XstartTime': 2.9, 'XendTime': 3.4, 'body': 'the' },"
                + "{ 'startTime': '-2.9', 'endTime': '-3.4', 'body': 'the' },"
                + "{ 'startTime': 'bad_time', 'endTime': '-3.4', 'body': 'the' }]}";
        result = TranscriptParser.parse(jsonStrBad2, type);
        assertNull(result);

        // Just plain text
        String strBad3 = "John Doe: Promoting your podcast in a new\n\n"
                + "way. The latest from PogNews.";
        result = TranscriptParser.parse(strBad3, type);
        assertNull(result);

        // passing the wrong type
        type = "application/srt";
        result = TranscriptParser.parse(jsonStr, type);
        assertEquals(result, null);
    }