private ClipDownloadData 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.PlayerUrl.Split(new char[] { '?' }, 2)[1]);
            var playerParametersObj = new
            {
                author          = playerParameters["author"],
                moduleName      = playerParameters["name"],
                courseName      = playerParameters["course"],
                clipIndex       = int.Parse(playerParameters["clip"]),
                mediaType       = "mp4",
                quality         = (clip.SupportsWideScreenVideoFormats ? "1280x720" : "1024x768"),
                includeCaptions = false,
                locale          = Constants.SUBTITLES_LOCALE
            };
            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.
            // Though it's simpler just to authenticate once and for all...
            if (Constants.USER_NAME.Length > 0)
            {
                SetupAuthenticationCookie(http);
            }
            try
            {
                using (var response = http.GetResponse())
                    using (var receiveStream = response.GetResponseStream())
                        using (var sr = new StreamReader(receiveStream))
                        {
                            var clipurl = sr.ReadToEnd();
                            return(JsonConvert.DeserializeObject <ClipDownloadData>(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.");
            }
        }
        public async Task <IHttpActionResult> DownloadCourseModuleClip(string clipname, ClipToSave clipToSave)
        {
            ClipDownloadData clipUrl = null;

            // 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.ModuleTitle, clipToSave);

                // 2b- create course information, if missing
                SaveCourseInformation(clipToSave);

                // 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.URLs[0].URL))
                        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 = videoSaveLocation
                };
                var outputFile = new MediaFile {
                    Filename = videoSaveDirectory.FullName + "\\" + videoFileName
                };

                if (File.Exists(outputFile.Filename))
                {
                    File.Delete(outputFile.Filename);
                }
                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);
                    if (srtString.Length > 4)
                    {
                        File.WriteAllText(srtFilename, srtString);
                        HandleEmbeddedSubtitles(outputFile.Filename, srtFilename);
                    }
                }

                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));
            }
        }