public async Task<IHttpActionResult> DownloadCourseModuleClip(string clipname, ClipToSave clipToSave)
        {
            string clipUrl = string.Empty;
            // 1- get the video clip url to download.
            try
            {
                clipUrl = GetClipUrl(clipToSave);

                // 2- make sure the folders structure exist.
                var videoSaveDirectory = SetUpVideoFolderStructure(clipToSave.CourseTitle,
                    (clipToSave.ModuleIndex + 1).ToString("D2") + " - " + clipToSave.ModuleTitle,
                    (clipToSave.ClipIndex + 1).ToString("D2") + " - " + clipToSave.Title);

                // 3- download the video and report progress back.
                int receivedBytes = 0;
                long totalBytes = 0;
                var videoFileName = ((clipToSave.ClipIndex + 1).ToString("D2") + " - " + clipToSave.Title + ".mp4").ToValidFileName();
                var videoSaveLocation = videoSaveDirectory.FullName + "\\raw-" + videoFileName;

                using (var client = new WebClient())
                using (var regStream = await client.OpenReadTaskAsync(clipUrl))
                using (var stream = new ThrottledStream(regStream, 115200))
                {
                    byte[] buffer = new byte[1024];
                    totalBytes = Int32.Parse(client.ResponseHeaders[HttpResponseHeader.ContentLength]);
                    stream.MaximumBytesPerSecond = GetClipMaxDownloadSpeed(clipToSave.DurationSeconds, totalBytes);

                    using (var fileStream = File.OpenWrite(videoSaveLocation))
                    {
                        for (;;)
                        {
                            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                            if (bytesRead == 0)
                            {
                                await Task.Yield();
                                break;
                            }

                            receivedBytes += bytesRead;
                            var progress = new ProgressArgs()
                            {
                                Id = clipToSave.Name,
                                BytesReceived = receivedBytes,
                                FileName = videoFileName,
                                TotalBytes = totalBytes,
                                IsDownloading = true,
                                Extra = new { clipToSave.ModuleIndex, clipToSave.ClipIndex }
                            };
                            fileStream.Write(buffer, 0, bytesRead);
                            var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
                            hubContext.Clients.All.updateProgress(progress);
                        }
                    }
                }

                // 4- save the video file.
                var inputFile = new MediaFile { Filename = videoSaveDirectory.FullName + "\\raw-" + videoFileName };
                var outputFile = new MediaFile { Filename = videoSaveDirectory.FullName + "\\" + videoFileName };

                File.Move(inputFile.Filename, outputFile.Filename);

                // 5- Create srt files
                if (Constants.SUBTITLES)
                {
                    var srtFilename = outputFile.Filename.Substring(0, outputFile.Filename.Length - 4) + ".srt";
                    var srtString = clipToSave.TranscriptClip.GetSrtString(clipToSave.DurationSeconds);
                    File.WriteAllText(srtFilename, srtString);
                }

                return Ok(new ProgressArgs()
                {
                    Id = clipToSave.Name,
                    BytesReceived = receivedBytes,
                    FileName = videoFileName,
                    TotalBytes = totalBytes,
                    IsDownloading = false,
                    Extra = new { clipToSave.ModuleIndex, clipToSave.ClipIndex }
                });
            }
            catch (Exception exception)
            {
                return HandleException(exception);
            }
        }
        private string GetClipUrl(ClipToSave clip)
        {
            var http = (HttpWebRequest)WebRequest.Create(new Uri(Constants.COURSE_CLIP_DATA_URL));
            http.Accept = "application/json";
            http.ContentType = "application/json";
            http.Method = "POST";
            http.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0";

            var playerParameters = HttpUtility.ParseQueryString(clip.PlayerParameters);
            var playerParametersObj = new
            {
                a = playerParameters["author"],
                m = playerParameters["name"],
                course = playerParameters["course"],
                cn = playerParameters["clip"],
                mt = "mp4",
                q = (clip.SupportsWideScreenVideoFormats ? "1280x720" : "1024x768"),
                cap = false,
                lc = "en"
            };
            var encoding = new ASCIIEncoding();
            Byte[] dataBytes = encoding.GetBytes(JsonConvert.SerializeObject(playerParametersObj));

            using (Stream sendStream = http.GetRequestStream())
                sendStream.Write(dataBytes, 0, dataBytes.Length);

            // if the clip is not free, then the user must sign in first and set authentication cookie.
            if (!clip.UserMayViewClip)
                SetupAuthenticationCookie(http);
            try
            {
                using (var response = http.GetResponse())
                using (var receiveStream = response.GetResponseStream())
                using (var sr = new StreamReader(receiveStream))
                {
                    var clipurl = sr.ReadToEnd();
                    return clipurl;
                }
            }
            catch
            {
                logger.Error("Couldn't retrieve clip URL. Request parameters={0}", JsonConvert.SerializeObject(playerParametersObj));
                throw new Exception("Couldn't retrieve clip URL. Please check log file.");
            }
        }