diff --git a/README-tw.md b/README-tw.md index 63bfba8..76161f0 100644 --- a/README-tw.md +++ b/README-tw.md @@ -58,18 +58,24 @@ GLOBAL OPTIONS: ## 中文對應 ``` -XXXXXX is online! fetching... -XXXXXX 正在線上!開始撈取實況內容… +XXX is online! fetching... +XXX 正在線上!開始撈取實況內容… -the video will be saved as "XXXXXX". -影片將會被保存為「XXXXXX」。 +the video will be saved as "XXX". +影片將會被保存為「XXX」。 -fetching XXXXXX.ts (size: XXXXXX) -正在擷取 XXXXXX.ts 片段(大小:XXXXXX) +fetching XXX.ts (size: XXX) +正在擷取 XXX.ts 片段(大小:XXX) failed to fetch the video segments, will try again. (1/2) 無法取得影片段落,稍後會重新嘗試。(1/2) -failed to fetch the video segments after retried, XXXXXX might went offline. -無法取得影片段落,XXXXXX 可能已經結束直播了。 +failed to fetch the video segments after retried, XXX might went offline. +無法取得影片段落,XXX 可能已經結束直播了。 + +cannot find segment XXX, will try again. (1/5) +無法找到影片段落,燒後會重新嘗試。(1/5) + +inserting XXX segment to the master file. +正在插入片段 XXX 至主要影片檔案。 ``` \ No newline at end of file diff --git a/bin/darwin/chaturbate-dvr b/bin/darwin/chaturbate-dvr index ecc1f18..6d84a1b 100644 Binary files a/bin/darwin/chaturbate-dvr and b/bin/darwin/chaturbate-dvr differ diff --git a/bin/linux/chaturbate-dvr b/bin/linux/chaturbate-dvr index ccb5cec..90e10a1 100644 Binary files a/bin/linux/chaturbate-dvr and b/bin/linux/chaturbate-dvr differ diff --git a/bin/windows/chaturbate-dvr.exe b/bin/windows/chaturbate-dvr.exe index 462e5df..489f5fb 100644 Binary files a/bin/windows/chaturbate-dvr.exe and b/bin/windows/chaturbate-dvr.exe differ diff --git a/main.go b/main.go index ba5eb19..67f2868 100644 --- a/main.go +++ b/main.go @@ -123,7 +123,7 @@ func parseM3U8Source(url string) (chunks []*m3u8.MediaSegment, wait float64, err // capture captures the specified channel streaming. func capture(username string) { // Define the video filename by current time. - filename := time.Now().String() + filename := time.Now().Format("2006-01-02_15-04-05") // Get the channel page content body. body := getBody(username) // Get the master playlist URL from extracting the channel body. @@ -135,6 +135,7 @@ func capture(username string) { // log.Printf("the video will be saved as \"%s\".", filename+".ts") + go combineSegment(masterFile, filename) watchStream(m3u8Source, username, masterFile, filename, baseURL) } @@ -184,6 +185,42 @@ func isDuplicateSegment(URI string) bool { return false } +// combineSegment combines the segments to the master video file in the background. +func combineSegment(master *os.File, filename string) { + index := 1 + var retry int + <-time.After(4 * time.Second) + + for { + <-time.After(800 * time.Millisecond) + + if !pathx.Exists(fmt.Sprintf("%s~%d.ts", filename, index)) { + if retry >= 5 { + index++ + retry = 0 + continue + } + if retry != 0 { + log.Printf("cannot find segment %d, will try again. (%d/5)", index, retry) + } + retry++ + <-time.After(time.Duration(1*retry) * time.Second) + continue + } + if retry != 0 { + retry = 0 + } + // + b, _ := ioutil.ReadFile(fmt.Sprintf("%s~%d.ts", filename, index)) + master.Write(b) + log.Printf("inserting %d segment to the master file.", index) + // + os.Remove(fmt.Sprintf("%s~%d.ts", filename, index)) + // + index++ + } +} + // fetchSegment fetches the segment and append to the master file. func fetchSegment(master *os.File, segment *m3u8.MediaSegment, baseURL string, filename string, index int) { _, body, _ := gorequest.New().Get(fmt.Sprintf("%s%s", baseURL, segment.URI)).EndBytes() @@ -199,29 +236,6 @@ func fetchSegment(master *os.File, segment *m3u8.MediaSegment, baseURL string, f if _, err := f.Write(body); err != nil { panic(err) } - // - var retry int - for { - if !pathx.Exists(fmt.Sprintf("%s~%d.ts", filename, index-1)) && retry < 3 { - retry++ - <-time.After(1 * time.Second) - } - break - } - // - if retry >= 3 { - // - b, _ := ioutil.ReadFile(fmt.Sprintf("%s~%d.ts", filename, index)) - master.Write(b) - // - os.Remove(fmt.Sprintf("%s~%d.ts", filename, index)) - return - } - // - b, _ := ioutil.ReadFile(fmt.Sprintf("%s~%d.ts", filename, index-1)) - master.Write(b) - // - os.Remove(fmt.Sprintf("%s~%d.ts", filename, index-1)) } // endpoint implements the application main function endpoint.