抖音通过分享信息获取,流地址

    科技2022-07-10  199

    下载抖音直播视频功能,代码比较简单,参考了某博客用python实现的的下载功能,原文地址:https://www.cnblogs.com/wuyongcong/p/12627370.html

    第一步:获取抖音直播分享短链接对应的长链接

     

    fun startALaunch(baseUrl: String, onConnectionCallBack: OnConnectionCallBack) {

    job = GlobalScope.launch {

    var con: HttpURLConnection = URL(baseUrl).openConnection() as HttpURLConnection

    con.instanceFollowRedirects = false

    con.connectTimeout = 5000

    val url: String = con.getHeaderField("Location")

    con.disconnect()

    onConnectionCallBack.onBack(url)

     

    }

     

    }

    第二部:通过接口,请求直播推流地址  

    fun getRtmpPullUrl(roomID: String) {

    if(!TextUtils.isEmpty(roomID)) {

    OkGo.get<String>("https://webcast-hl.amemv.com/webcast/room/reflow/info/")

    .params("room_id", roomID)

    .params("live_id", 1)

    .execute(object : StringCallback() {

    override fun onSuccess(response: Response<String>?) {

    if (response != null) {

    logged("response:" + response.body())

    var data =

    getMap(response.body().toString()).get("data") as Map<String, Any>

    var room = data.get("room") as Map<String, Any>

    var stream_url = room.get("stream_url") as Map<String, Any>

    var rtmp_pull_url = stream_url.get("rtmp_pull_url")

    var msg = Message()

    msg.what = 4

    msg.obj = rtmp_pull_url

    handler.sendMessage(msg)

    }

    }

     

    })

    }

    }

    完整代码:  

    class MainActivity : AppCompatActivity() {

    var job: Job? = null

    val re = Regex("""(\d{19})""")

    val gson = Gson()

      

    var handler = object :Handler(){

    override fun handleMessage(msg: Message) {

    super.handleMessage(msg)

    when(msg.what){

    0 ->{

    textview.setText("直播短链接:"+msg.obj)

    }

    1 ->{

    initPostUrl(msg.obj as String)

    }

    2 ->{

    initRtmpPullUrl(msg.obj as String)

    }

    3 ->{

    getRtmpPullUrl(msg.obj as String)

    }

    4 ->{

    textview3.setText("推流地址:${msg.obj}")

    startForBrowser(msg.obj as String)

    }

    }

    }

     

    }

    override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main )

    initBaseString()

    initRid()

       

    }

     

    /**

    * 获取直播短链接

    */

    fun initBaseString(){

    edittext.addTextChangedListener(object :TextWatcher{

    override fun afterTextChanged(s: Editable?) {

    var baseString = edittext.text.toString()

    //判断分享过来的是否是抖音的短链接

    if(baseString.contains(" https://v.douyin.com")) {

    var msg = Message()

    msg.what = 0;

    msg.obj = baseString.split("!")[1] //拆分分享短连接的文案、链接

    handler.sendMessage(msg)

    }

    }

     

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

    }

     

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

    }

     

    })

    }

     

    /**

    * 获取直播长链接

    */

    fun initRid(){

    button.setOnClickListener(object : View.OnClickListener {

    override fun onClick(v: View?) {

    var rid: String = textview.text.toString().replace("直播短链接:","")

     

    if(!TextUtils.isEmpty(rid)) {

    var msg = Message()

    msg.what = 1

    msg.obj = rid

    handler.sendMessage(msg)

    }

    }

     

    })

    }

    fun startForBrowser(tempUrl:String){

    if(!TextUtils.isEmpty(tempUrl)) {

    textview3.setOnClickListener(object : View.OnClickListener {

    override fun onClick(v: View?) {

    var uri = Uri.parse(tempUrl)

    var intent = Intent(Intent.ACTION_VIEW, uri)

    startActivity(intent)

    }

     

    })

     

    }

    }

     

    /**

    * 获取请求链接地址

    */

    fun initPostUrl(rid:String){

     

    if(!TextUtils.isEmpty(rid)) {

    startALaunch(rid, object : OnConnectionCallBack {

    override fun onBack(string: String) {

    if (job != null) {

    job!!.cancel()

    }

    var msg = Message()

    msg.what = 2

    msg.obj = string

    handler.sendMessage(msg)

     

    }

     

    })

    }

    }

     

    /**

    * 获取推流地址

    */

    fun initRtmpPullUrl(postUrl:String ){

    if(!TextUtils.isEmpty(postUrl)) {

    var room_id = re.findAll(postUrl)

    room_id.forEach {

    var msg = Message()

    msg.what = 3

    msg.obj = it.value

    handler.sendMessage(msg)

     

    }

    }

    }

      

    /**

    * 请求推流地址的接口

    */

    fun getRtmpPullUrl(roomID: String) {

    if(!TextUtils.isEmpty(roomID)) {

    OkGo.get<String>("https://webcast-hl.amemv.com/webcast/room/reflow/info/")

    .params("room_id", roomID)

    .params("live_id", 1)

    .execute(object : StringCallback() {

    override fun onSuccess(response: Response<String>?) {

    if (response != null) {

    logged("response:" + response.body())

    var data =

    getMap(response.body().toString()).get("data") as Map<String, Any>

    var room = data.get("room") as Map<String, Any>

    var stream_url = room.get("stream_url") as Map<String, Any>

    var rtmp_pull_url = stream_url.get("rtmp_pull_url")

    var msg = Message()

    msg.what = 4

    msg.obj = rtmp_pull_url

    handler.sendMessage(msg)

    }

    }

     

    })

    }

    }

     

    /**

    * 解析获取推流地址接口返回的数据

    */

    fun getMap(json: String): Map<String, Any> {

    var map = gson.fromJson<Map<String, Any>>(

    json,

    object : TypeToken<Map<String, Any>>() {}.type

    ) as Map<String, Any>

    return map

    }

     

    /**

    * 解析成长链接

    */

    fun startALaunch(baseUrl: String, onConnectionCallBack: OnConnectionCallBack) {

    job = GlobalScope.launch {

    var con: HttpURLConnection = URL(baseUrl).openConnection() as HttpURLConnection

    con.instanceFollowRedirects = false

    con.connectTimeout = 5000

    val url: String = con.getHeaderField("Location")

    con.disconnect()

    onConnectionCallBack.onBack(url)

     

    }

     

    }

       

    interface OnConnectionCallBack {

    fun onBack(string: String)

    }

     

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {

    if (keyCode === KeyEvent.KEYCODE_BACK) {

    val home = Intent(Intent.ACTION_MAIN)

    home.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP

    home.addCategory(Intent.CATEGORY_HOME)

    startActivity(home)

    return true

    }

    return super.onKeyDown(keyCode, event)

    }

     

    fun logged(param: String) {

    Log.d("MyKotlinLog", param)

    }

    fun toast(param: String){

    Toast.makeText(this,param, Toast.LENGTH_SHORT)

    }

    }

    布局界面 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/edittext" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:hint="请粘贴抖音分享链接到这里" /> <TextView android:id="@+id/textview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/edittext" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:textColor="#000000" android:textSize="16sp"/> <TextView android:id="@+id/textview3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/textview" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:textIsSelectable="true" android:textColor="#000000" android:textSize="16sp" /> <TextView android:id="@+id/textView4" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_below="@id/textview3" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:textSize="14sp" android:text="(点击链接到浏览器下载视频或长按链接复制在浏览器打开)"/> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/textView4" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:text="获取下载地址"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="下载过程中请不要关闭浏览器" android:layout_alignParentBottom="true" android:textSize="16sp" android:gravity="center_horizontal"/> </RelativeLayout>
    Processed: 0.012, SQL: 8