Skip to content

Downloading Echo360 videos

Published Jan 8, 2025

This solution comes partly courtesy of this GitHub comment.

Background

Echo360 is a video platform commonly used by higher-level educational institutions for teachers to post class materials. It is quite a slick platform, but unfortunately downloading videos from it is pretty hard. If you want to watch the videos offline or have more granular control over the video speed, at first glance, you are out of luck. Unlike Zoom recordings, you cannot easily right click and save the videos.

Echo360 videos are served via m3u8 streams. If you try to open these m3u8 streams using a tool like ffmpeg, you will find that it throws 403 - Forbidden error codes every time (I might just be bad at this though). This is probably due to the cookies that are set in the session that authenticate the browser.

Fortunately, a look at the DevTools Network tab reveals that .m4s files are requested. These .m4s files can be downloaded, then converted into .mp4 files.

Procedures

Video

  • Ensure you have ffmpeg installed.
  • Open your DevTools pane and navigate to the Echo360's video page (with the video player, transcript, etc.)
  • In the Network tab of the DevTools pane, search for .m4s. You want requests with names beginning with s1q1 and s0q1. s0 means audio, s1 means video, and q1 indicates best quality.
  • Click on the s1q1 and s0q1 requests and copy their Request URL's. Open both of these links in a new tab. Your browser should prompt you to download the .m4s files.
  • Convert the .m4s files to .mp4 files by executing ffmpeg -i s0q1.m4s -c copy audio.mp4 and ffmpeg -i s1q1.m4s -c copy video.mp4.
  • Merge the video and audio files into a single output file by executing ffmpeg -i video.mp4 -i audio.mp4 -c copy -map 0:v:0 -map 1:a:0 final.mp4, where final.mp4 is the output file.
  • Done!

Transcript

The transcript of the video (if available) may also be downloaded. I wasn't able to locate a .vtt file to directly download, so I resorted to converting the raw json data that is requested into the VTT format using a Python script (generated by ChatGPT because I'm lazy).

First, grab the transcript json. Head back to the DevTools tab and search for transcript. Right click on the request > Copy > Copy response. Paste into a empty file and save. This will be your input file into the Python script shown below.

import json
import argparse

# Function to convert milliseconds to VTT timestamp format
def ms_to_vtt_time(ms):
    hours = ms // 3600000
    minutes = (ms % 3600000) // 60000
    seconds = (ms % 60000) // 1000
    milliseconds = ms % 1000
    return f"{hours:02}:{minutes:02}:{seconds:02}.{milliseconds:03}"

# Function to process JSON data from a file and create .vtt file
def json_to_vtt(input_json_file, output_vtt_file):
    # Open the JSON file and load the data
    with open(input_json_file, 'r') as f:
        json_data = json.load(f)

    # Open output .vtt file for writing
    with open(output_vtt_file, 'w') as f:
        # Write WebVTT header
        f.write("WEBVTT\n\n")

        # Loop through each cue in the "cues" list
        for index, cue in enumerate(json_data["data"]["contentJSON"]["cues"]):
            # Get the start and end time in milliseconds
            start_time = ms_to_vtt_time(cue["startMs"])
            end_time = ms_to_vtt_time(cue["endMs"])

            # Write the cue in VTT format
            f.write(f"{index + 1}\n")  # Cue number
            f.write(f"{start_time} --> {end_time}\n")  # Start and end time
            f.write(f"{cue['content']}\n\n")  # Subtitle content

def main():
    # Set up argument parser
    parser = argparse.ArgumentParser(description="Convert JSON subtitles to WebVTT format.")

    # Add arguments for input and output files
    parser.add_argument("input_json", help="Path to the input JSON file")
    parser.add_argument("output_vtt", help="Path to the output VTT file")

    # Parse the arguments
    args = parser.parse_args()

    # Call the function to process the files
    json_to_vtt(args.input_json, args.output_vtt)

    print(f"VTT file has been created: {args.output_vtt}")

# Run the script
if __name__ == "__main__":
    main()

Use the script by executing python convert_to_vtt.py <input json file> <output vtt file.vtt> (assuming you saved the above script as convert_to_vtt.py).

Playing

At this point, you have your video file and your subtitles file. Play them together using VLC or a similar program. It might help to rename the .mp4 and .vtt files to be the same so the subs file can be autorecognized.