diff --git a/.gitignore b/.gitignore index a995fe8..6482575 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ *.db *.sqlite *.sqlite3 +*-journal diff --git a/src/buildno/buildno.go b/src/buildno/buildno.go index 69c57a4..23a9d09 100644 --- a/src/buildno/buildno.go +++ b/src/buildno/buildno.go @@ -1,5 +1,5 @@ package buildno -var BuildDate = "20180716" -var BuildNo = "18" +var BuildDate = "20180718" +var BuildNo = "19" diff --git a/src/niconico/nico_db.go b/src/niconico/nico_db.go index 52176c3..64b320d 100644 --- a/src/niconico/nico_db.go +++ b/src/niconico/nico_db.go @@ -382,3 +382,17 @@ func WriteComment(db *sql.DB, fileName string) { } fmt.Fprintln(f, ``) } + +// ts +func (hls *NicoHls) dbGetLastMedia(i int) (res []byte) { + hls.dbMtx.Lock() + defer hls.dbMtx.Unlock() + hls.db.QueryRow("SELECT data FROM media WHERE seqno = ?", i).Scan(&res) + return +} +func (hls *NicoHls) dbGetLastSeqNo() (res int64) { + hls.dbMtx.Lock() + defer hls.dbMtx.Unlock() + hls.db.QueryRow("SELECT seqno FROM media ORDER BY seqno DESC LIMIT 1").Scan(&res) + return +} \ No newline at end of file diff --git a/src/niconico/nico_hls.go b/src/niconico/nico_hls.go index c291740..7a76051 100644 --- a/src/niconico/nico_hls.go +++ b/src/niconico/nico_hls.go @@ -29,6 +29,8 @@ import ( _ "net/http/pprof" "../httpbase" + "github.com/gin-gonic/gin" + "context" ) type OBJ = map[string]interface{} @@ -1533,7 +1535,79 @@ func (hls *NicoHls) dbOpen() (err error) { return } -func (hls *NicoHls) Wait(testTimeout int) { +func (hls *NicoHls) serve(hlsPort int) { + hls.startMGoroutine(func(sig chan struct{}) int { + gin.SetMode(gin.ReleaseMode) + router := gin.Default() + + router.GET("", func(c *gin.Context) { + seqno := hls.dbGetLastSeqNo() + body := fmt.Sprintf( +`#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-TARGETDURATION:1 +#EXT-X-MEDIA-SEQUENCE:%d + +#EXTINF:1.0, +/ts/%d/test.ts + +#EXTINF:1.0, +/ts/%d/test.ts + +#EXTINF:1.0, +/ts/%d/test.ts + +`, seqno - 2, seqno - 2, seqno - 1, seqno) + c.Data(http.StatusOK, "application/x-mpegURL", []byte(body)) + return + }) + + router.GET("/ts/:idx/test.ts", func(c *gin.Context) { + i, _ := strconv.Atoi(c.Param("idx")) + b := hls.dbGetLastMedia(i) + c.Data(http.StatusOK, "video/MP2T", b) + return + }) + + srv := &http.Server{ + Addr: fmt.Sprintf("127.0.0.1:%d", hlsPort), + Handler: router, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + + chLocal := make(chan struct{}) + idleConnsClosed := make(chan struct{}) + defer func(){ + close(chLocal) + }() + go func() { + select { + case <-chLocal: + case <-sig: + } + if err := srv.Shutdown(context.Background()); err != nil { + log.Printf("srv.Shutdown: %v\n", err) + } + close(idleConnsClosed) + }() + + // クライアントはlocalhostでなく127.0.0.1で接続すること + // localhostは遅いため + if err := srv.ListenAndServe(); err != http.ErrServerClosed { + log.Printf("srv.ListenAndServe: %v\n", err) + } + + <-idleConnsClosed + return OK + }) +} + +func (hls *NicoHls) Wait(testTimeout, hlsPort int) { + + hls.startInterrupt() + defer hls.stopInterrupt() if testTimeout > 0 { hls.startMGoroutine(func(sig chan struct{}) int { @@ -1547,8 +1621,9 @@ func (hls *NicoHls) Wait(testTimeout int) { }) } - hls.startInterrupt() - defer hls.stopInterrupt() + if hlsPort > 0 { + hls.serve(hlsPort) + } hls.startMain() for hls.working() { @@ -1765,7 +1840,7 @@ func NicoRecHls(opt options.Option) (done, notLogin bool, err error) { */ - hls.Wait(opt.NicoTestTimeout) + hls.Wait(opt.NicoTestTimeout, opt.NicoHlsPort) done = true diff --git a/src/options/options.go b/src/options/options.go index 8d2e30c..d96cdd1 100644 --- a/src/options/options.go +++ b/src/options/options.go @@ -31,6 +31,7 @@ type Option struct { ConfPass string ZipFile string DBFile string + NicoHlsPort int } func getCmd() (cmd string) { cmd = filepath.Base(os.Args[0]) @@ -68,7 +69,8 @@ COMMAND: -nico-rtmp-only 録画時にRTMPのみを試す -nico-rtmp-max-conn RTMPの同時接続数を設定 -nico-rtmp-index [,] RTMP録画を行うメディアファイルの番号を指定 - -nico-status-https [実験的] getplayerstatusの取得にhttpsを使用する + -nico-status-https [廃止] getplayerstatusの取得にhttpsを使用する + -nico-hls-port [実験的] ローカルなHLSサーバのポート番号 COMMAND(debugging) -nico-test-run (debugging) test for nicolive @@ -224,6 +226,21 @@ func ParseArgs() (opt Option) { opt.NicoStatusHTTPS = true return nil }}, + Parser{regexp.MustCompile(`\A(?i)--?nico-?hls-?port\z`), func() (err error) { + s, err := nextArg() + if err != nil { + return err + } + num, err := strconv.Atoi(s) + if err != nil { + return fmt.Errorf("--nico-hls-port: Not a number: %s\n", s) + } + if num <= 0 { + return fmt.Errorf("--nico-hls-port: Invalid: %d: must be greater than or equal to 1\n", num) + } + opt.NicoHlsPort = num + return nil + }}, Parser{regexp.MustCompile(`\A(?i)--?nico-?login\z`), func() (err error) { str, err := nextArg() if err != nil {