Skip to content

Instantly share code, notes, and snippets.

@pisual
Forked from sunny00123/liverecord.groovy
Created August 15, 2016 12:52
Show Gist options
  • Save pisual/5f9943bced4baa213b185e6b4325c796 to your computer and use it in GitHub Desktop.
Save pisual/5f9943bced4baa213b185e6b4325c796 to your computer and use it in GitHub Desktop.
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
def UID = "276904" // B站用户UID
def ROOMID = "131985" // 直播间的房间编号,不是地址编号
def OUTPUTDIR = /D:\Users\Sun\Desktop\ffmpeg\bin/ // 录制文件输出目录
def FFMPEG = /D:\Users\Sun\Desktop\ffmpeg\bin\ffmpeg.exe/ // ffmpeg可执行程序位置
def DELAY = 30 // SECONDS // 监控线程的间隔,当检测到直播时开启一个ffmpeg进程进行录制
def scheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
def counter = 0
def isliving = false
def isrecording = false
Process process
scheduledExecutorService.scheduleWithFixedDelay({
def islivingurl = new URL("http://live.bilibili.com/bili/isliving/$UID").text
isliving = !islivingurl.contains(/"data":""/)
if (isliving) { // 开始直播了
if (!isrecording) { // 如果没有录制,则开始录制
println "[${Calendar.getInstance().format("yyyy-MM-dd HH:mm:ss")}] 正在直播中"
println "[${Calendar.getInstance().format("yyyy-MM-dd HH:mm:ss")}] 开始录制了"
isrecording = true
Thread thread = new Thread({ // 开启一个守护线程去启动ffmpeg的进程防止阻塞监控线程
def h5play = new URL("http://live.bilibili.com/api/h5playurl?roomid=$ROOMID").text
def matcher = h5play =~ /"url":"(.+)"/
if (matcher.find()) {
def m3u8 = matcher.group(1)
String[] command = [FFMPEG,
"-i", "$m3u8",
"-acodec", "copy",
"-bsf:a", "aac_adtstoasc",
"-vcodec", "copy",
"-f", "mp4",
"${Calendar.getInstance().format("yyyy-MM-dd-HH-mm-ss")}.mp4"]
process = command.execute null, new File(OUTPUTDIR)
process.addShutdownHook { // 监听ctrl+c的事件,退出时发送q到ffmpeg进程,避免出现 moov atom not found 错误
quitFFmpeg process
scheduledExecutorService.shutdown()
}
process.waitForProcessOutput System.out, System.err
} else {
println "[${Calendar.getInstance().format("yyyy-MM-dd HH:mm:ss")}] 无法获取直播流地址"
counter++
if (counter == 10) { // 无法获取直播地址时,退出程序
quitFFmpeg process
scheduledExecutorService.shutdown()
}
}
})
thread.setDaemon(true)
thread.start()
}
} else { // 未检测到直播
if (process == null || !process.alive) { // 如果当前没有ffmpeg的进程,则没有直播
println "[${Calendar.getInstance().format("yyyy-MM-dd HH:mm:ss")}] 还没有直播"
} else { // 如果当前有ffmpeg的进程,发送q到ffmpeg使其退出
println "[${Calendar.getInstance().format("yyyy-MM-dd HH:mm:ss")}] 直播关闭了"
quitFFmpeg process
isrecording = false
}
}
}, 0, DELAY, TimeUnit.SECONDS)
static void quitFFmpeg(Process process) {
if (process.alive) {
def writer = new BufferedWriter(new OutputStreamWriter(process.outputStream))
writer.write("q")
writer.flush()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment