安卓手机开发培训直播为什么会掉

android(41)
客户端的话最主要就是使用ffmpeg。
接下来要讲的就是从ffmpeg的编译开始,到编码,以及推流,到解码等过程。
ffmpeg的编译
懂英文看这里就行:
ffmpeg的编译需要linux环境,我这里使用的是虚拟机(vmware+ubuntu),软件的话大家自己网上下载就行,这里需要注意的就是vmTools的安装,可参考,如果你不安装vmtools的话就不能直接拖动文件到虚拟机,就很麻烦。总之按照上面的百度经验的方法安装了之后就能直接拖动文件到虚拟机,总之就很方便。
接下来进入正文,首先下载ffmpeg的压缩包,,你直接百度ffmpeg也行,进入官网之后直接下载就行(中间最明显的那个Download直接按下去,不要犹豫)。
下载之后进入,蛋疼的编译。。。把压缩包拖到ubuntu中,放在哪个目录中随便,我的话是在桌面建了一个文件夹sqq。然后把压缩包放在sqq下面。
1、打开终端(ctrl+alt+t)或者上级sqq文件夹,右键open in terminal
2、右键的同学直接就tar jxvf ffmpeg-x.x.x.tar.bz2 ,快捷键打开的同学就cd到sqq目录,注意这里解压的命令,可参考:。
上面的工作就完成了解压,其实因为是yoga的ubuntu所以解压可以直接右键 extract here,哈哈哈哈。。。。不要打我!既然用了linux系统就多用一下命令行,没毛病。
解压之后,大家就可以去看看雷神的博客了:
大家可能在其他地方百度到一些在linux下编译ffmpeg的博客,但是很多都不是针对android的,直接编译的在android上无法使用,因为android是arm的cpu,而我们一般的电脑是x86之类的,所以需要交叉编译,也就需要在linux下载用ndk。具体的操作就去看雷神的博客。
1、这里你可能会遇到no working c compiler 的问题,去看下解压出来的文件夹下的config.log,一般是因为ndk的路径写错了,(遇到这个问题,可能有人会去叫你配置环境变量之类的,我告诉你不需要,只要把路径写对就行)。
2、这里简单介绍几个指令的意思
–enable-shared 这是 configure 常用的一个参数,表示启用动态库版本。
如果你要编译一个库的源代码,可以把它编译成静态库,也可以把它编译成动态库。如果你想编译成静态库,就用 –enable-shared参数;如果你想编译成静态库,就用–enable-static参数。动态库是运行时加载,静态库就相当于写在自己的代码中。
–prefix=/usr/local/ffmpeg 指定安装路径
不指定prefix,则可执行文件默认放在/usr /local/bin,库文件默认放在/usr/local/lib,配置文件默认放在/usr/local/etc。其它的资源文件放在/usr /local/share。你要卸载这个程序,要么在原来的make目录下用一次make uninstall(前提是make文件指定过uninstall),要么去上述目录里面把相关的文件一个个手工删掉。
指定prefix,直接删掉一个文件夹就够了。
–disable-yasm
编译FFMPEG时不加的话会出现 ffmpeg yasm not found, use –disable-yasm for a crippled build的错误,是因为 FFMPEG为了提高编译速度,使用了汇编指令,如果系统中没有yasm指令的话,就会出现上述的问题。所以就直接disable就可以了
正常的按照上面的步骤走下来应该就完成了编译工作。
这个时候你会很高兴的去把生成的文件从虚拟机中复制出来,很可能会出现复制不出来的问题,我的方法是直接压缩然后就可以复制了。很简单。
客户端技术要点
完成了编译之后,不能说你已经进入了音视频技术界,但是绝对可以吹逼说自己会linux,是不是很开心。不逼逼了,进入正题讲一讲,怎么使用ffmpeg做客户端的直播。
其实在讲下面的内容之前,大家最好是先有一点音视频编码的基础,这里我就不详细说了,不要问我为什么,我tmd也是个菜逼。
像我们一般做android应用,牵扯到音视频开发,无非就是调用一下系统的api,用的最多的可能是MediaRecorder,底层一点录制音频用AudioRecord,播放用AudioTrack,录制视频用Camera。用MediaRecorder的话其实就是硬编码,用硬编码其实速度应该是最快的,但是牵扯到适配的问题(不同的厂商封装的格式之类的会有区别),所以我这里还是选择使用软编码,也就是自己做编码工作,编码其实就是个压缩的过程,去掉一些不影响质量又不需要的数据,比如声音,人耳能听到的也就20hz~20khz之间,其他的就都是多余数据可以去掉。
不扯了进入正题,我这里也就按照我自己的实现流程去讲好了。不管你理解不理解。
首先android使用Camera采集原始视频数据,android摄像头采集的数据是NV21格式的,需要先转换成YUV420p格式随后使用ffmpeg编码成h264.
其次android使用AudioRecord采集音频数据,采集的音频数据是pcm格式的,可以直接使用ffmpeg编码成aac的。
(上面不懂aac、h264之类的先去补一下音视频知识,不然就不要继续看了,没意义的,兄弟!)
在很多地方看到,在完成了上面的两个步骤之后说还需要做音视频的同步,我这里音视频编码的时候使用的时间戳都是使用的系统的时间,倒是没有出现播放的时候不同步的情况,但是出现了加速的问题,单独视频或者音频倒是对的,说明还是需要做同步,我的项目中暂时还没有做,大家凑活着看下先。
AVBitStreamFilterContext* faacbsfc = NULL;
AVFormatContext *ofmt_ctx /*,*fmt_ctx*/;
AVCodec* pCodec,*pCodec_a;
AVCodecContext* pCodecCtx,*pCodecCtx_a;
AVStream* video_st,*audio_st;
AVPacket enc_pkt,enc_pkt_a;
AVFrame *pFrameYUV,*pFrame;
//AVAudioFifo *fifo;
//int output_frame_
char *filedir;
int width = 600;
int height = 800;
int framecnt = 0;
int framecnt_a = 0;
int nb_samples = 0;
int64_t start_
int init_video(){
//编码器的初始化
pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!pCodec){
LOGE("Can not find video encoder!\n");
return -1;
pCodecCtx = avcodec_alloc_context3(pCodec);
pCodecCtx-&pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx-&width =
pCodecCtx-&height =
pCodecCtx-&time_base.num = 1;
pCodecCtx-&time_base.den = 30;
pCodecCtx-&bit_rate = 800000;
pCodecCtx-&gop_size = 30;
/* Some formats want stream headers to be separate. */
if (ofmt_ctx-&oformat-&flags & AVFMT_GLOBALHEADER)
pCodecCtx-&flags |= CODEC_FLAG_GLOBAL_HEADER;
pCodecCtx-&qmin = 10;
pCodecCtx-&qmax = 51;
//Optional Param
pCodecCtx-&max_b_frames = 3;
// Set H264 preset and tune
AVDictionary *param = 0;
av_dict_set(&param, "preset", "ultrafast", 0);
av_dict_set(&param, "tune", "zerolatency", 0);
if (avcodec_open2(pCodecCtx, pCodec, &param) & 0){
LOGE("Failed to open video encoder!\n");
return -1;
//Add a new stream to output,should be called by the user before avformat_write_header() for muxing
video_st = avformat_new_stream(ofmt_ctx, pCodec);
if (video_st == NULL){
return -1;
video_st-&time_base.num = 1;
video_st-&time_base.den = 30;
video_st-&codec = pCodecC
int init_audio(){
pCodec_a = avcodec_find_encoder(AV_CODEC_ID_AAC);
if(!pCodec_a){
LOGE("Can not find audio encoder!\n");
return -1;
pCodecCtx_a = avcodec_alloc_context3(pCodec_a);
pCodecCtx_a-&channels = 2;
//pCodecCtx_a-&channel_layout = av_get_default_channel_layout(2);
pCodecCtx_a-&channel_layout = av_get_default_channel_layout(
pCodecCtx_a-&channels);
pCodecCtx_a-&sample_rate = 44100;//44100 8000
//pCodecCtx_a-&sample_fmt = pCodec_a-&sample_fmts[0];
pCodecCtx_a-&sample_fmt = AV_SAMPLE_FMT_S16;
pCodecCtx_a-&bit_rate = 64000;
pCodecCtx_a-&time_base.num = 1;
pCodecCtx_a-&time_base.den = pCodecCtx_a-&sample_
pCodecCtx_a-&strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
/* Some formats want stream headers to be separate. */
if (ofmt_ctx-&oformat-&flags & AVFMT_GLOBALHEADER)
pCodecCtx_a-&flags |= CODEC_FLAG_GLOBAL_HEADER;
if(avcodec_open2(pCodecCtx_a,pCodec_a,NULL)&0){
LOGE("Failed to open audio encoder!\n");
return -1;
audio_st = avformat_new_stream(ofmt_ctx,pCodec_a);
if(audio_st == NULL){
return -1;
audio_st-&time_base.num = 1;
audio_st-&time_base.den = pCodecCtx_a-&sample_
audio_st-&codec = pCodecCtx_a;
//fifo = av_audio_fifo_alloc(pCodecCtx_a-&sample_fmt,pCodecCtx_a-&channels,1);
//output_frame_size = pCodecCtx_a-&frame_
com_example_sqqfinalrecord_FfmpegHelper
* Signature: ([B)I
JNIEXPORT jint JNICALL Java_com_example_sqqfinalrecord_FfmpegHelper_init
(JNIEnv *env, jclass cls, jbyteArray filename /*,jbyteArray path*/){
//filedir = (char*)(*env)-&GetByteArrayElements(env, filename, 0);
//const char* out_path = "rtmp://10.0.3.114:1935/live/demo";
const char* out_path = "rtmp://10.0.6.114:1935/live/demo";
yuv_width=
yuv_height=
y_length=width*height;
uv_length=width*height/4;
av_register_all();
faacbsfc =
av_bitstream_filter_init("aac_adtstoasc");
//初始化输出格式上下文
avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_path/*filedir*/);
if(init_video()!=0){
return -1;
if(init_audio()!=0){
return -1;
//Open output URL,set before avformat_write_header() for muxing
if (avio_open(&ofmt_ctx-&pb, /*filedir*/out_path, AVIO_FLAG_READ_WRITE) & 0){
LOGE("Failed to open output file!\n");
return -1;
//Write File Header
avformat_write_header(ofmt_ctx, NULL);
start_time = av_gettime();
com_example_sqqfinalrecord_FfmpegHelper
* Signature: ([B)I
JNIEXPORT jint JNICALL Java_com_example_sqqfinalrecord_FfmpegHelper_start
(JNIEnv *env, jclass cls, jbyteArray yuv){
//传递进来yuv数据
int enc_got_frame=0;
pFrameYUV = av_frame_alloc();
uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx-&width, pCodecCtx-&height));
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx-&width, pCodecCtx-&height);
jbyte* in= (jbyte*)(*env)-&GetByteArrayElements(env,yuv,0);
memcpy(pFrameYUV-&data[0],in,y_length);
(*env)-&ReleaseByteArrayElements(env,yuv,in,0);
for(i=0;i&uv_i++)
*(pFrameYUV-&data[2]+i)=*(in+y_length+i*2);
*(pFrameYUV-&data[1]+i)=*(in+y_length+i*2+1);
/*int y_size = pCodecCtx-&width * pCodecCtx-&
//pFrameYUV-&pts =
pFrameYUV-&data[0] =
pFrameYUV-&data[1] = in+ y_
pFrameYUV-&data[2] = in+ y_size*5/4;
pFrameYUV-&format = AV_PIX_FMT_YUV420P;
pFrameYUV-&width = yuv_
pFrameYUV-&height = yuv_
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2(pCodecCtx, &enc_pkt, pFrameYUV, &enc_got_frame);
av_frame_free(&pFrameYUV);
if (enc_got_frame == 1){
LOGI("Succeed to encode video frame: %5d\tsize:%5d\n", framecnt, enc_pkt.size);
framecnt++;
enc_pkt.stream_index = video_st-&index;
//Write PTS
AVRational time_base=ofmt_ctx-&streams[0]-&time_
//表示一秒30帧
AVRational r_framerate1 = {30, 1 };
AVRational time_base_q = AV_TIME_BASE_Q;
//Duration between 2 frames (us)两帧之间的时间间隔,这里的单位是微秒
int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / av_q2d(r_framerate1));
//内部时间戳
//Parameters
int64_t timett = av_gettime();
int64_t now_time = timett - start_
enc_pkt.pts = av_rescale_q(now_time, time_base_q, time_base);;
enc_pkt.dts=enc_pkt.
enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base);
enc_pkt.pos = -1;
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
av_free_packet(&enc_pkt);
com_example_sqqfinalrecord_FfmpegHelper
startAudio
* Signature: ()I
JNIEXPORT jint JNICALL Java_com_example_sqqfinalrecord_FfmpegHelper_startAudio
(JNIEnv *env, jclass cls, jbyteArray au_data,jint datasize){
//传递进来pcm数据
int enc_got_frame=0;
pFrame = av_frame_alloc();
pFrame-&nb_samples = pCodecCtx_a-&frame_
pFrame-&format = pCodecCtx_a-&sample_
pFrame-&channel_layout = pCodecCtx_a-&channel_
pFrame-&sample_rate = pCodecCtx_a-&sample_
int size = av_samples_get_buffer_size(NULL,pCodecCtx_a-&channels,
pCodecCtx_a-&frame_size,pCodecCtx_a-&sample_fmt,1);
uint8_t *frame_buf = (uint8_t *)av_malloc(size*4);
avcodec_fill_audio_frame(pFrame,pCodecCtx_a-&channels,pCodecCtx_a-&sample_fmt,(const uint8_t *)frame_buf,size,1);
jbyte* in= (jbyte*)(*env)-&GetByteArrayElements(env,au_data,0);
if(memcpy(frame_buf,in,datasize)&=0){
LOGE("Failed to read raw data!");
return -1;
pFrame-&data[0] = frame_
(*env)-&ReleaseByteArrayElements(env,au_data,in,0);
enc_pkt_a.data = NULL;
enc_pkt_a.size = 0;
av_init_packet(&enc_pkt_a);
ret = avcodec_encode_audio2(pCodecCtx_a,&enc_pkt_a,pFrame, &enc_got_frame);
av_frame_free(&pFrame);
if (enc_got_frame == 1){
LOGI("Succeed to encode audio frame: %5d\tsize:%5d\t bufsize:%5d\n ", framecnt_a, enc_pkt_a.size,size);
framecnt_a++;
enc_pkt_a.stream_index = audio_st-&index;
av_bitstream_filter_filter(faacbsfc, pCodecCtx_a, NULL, &enc_pkt_a.data, &enc_pkt_a.size, enc_pkt_a.data, enc_pkt_a.size, 0);
//Write PTS
AVRational time_base=ofmt_ctx-&streams[audio_st-&index]-&time_
//表示一秒30帧
AVRational r_framerate1 = {pCodecCtx_a-&sample_rate, 1 };
AVRational time_base_q = AV_TIME_BASE_Q;
//Duration between 2 frames (us)两帧之间的时间间隔,这里的单位是微秒
int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / av_q2d(r_framerate1));
//内部时间戳
enc_pkt_a.pts = av_rescale_q(nb_samples*calc_duration, time_base_q, time_base);
enc_pkt_a.dts=enc_pkt_a.
enc_pkt_a.duration = av_rescale_q(calc_duration, time_base_q, time_base);*/
//Parameters
int64_t timett = av_gettime();
int64_t now_time = timett - start_
enc_pkt_a.pts = av_rescale_q(now_time, time_base_q, time_base);;
enc_pkt_a.dts=enc_pkt_a.
enc_pkt_a.duration = av_rescale_q(calc_duration, time_base_q, time_base);
enc_pkt_a.pos = -1;
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt_a);
av_free_packet(&enc_pkt_a);
int flush_encoder(){
AVPacket enc_
if (!(ofmt_ctx-&streams[0]-&codec-&codec-&capabilities &
CODEC_CAP_DELAY))
while (1) {
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2(ofmt_ctx-&streams[0]-&codec, &enc_pkt,
NULL, &got_frame);
if (ret & 0)
if (!got_frame){
LOGI("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n", enc_pkt.size);
//Write PTS
AVRational time_base = ofmt_ctx-&streams[0]-&time_//{ 1, 1000 };
AVRational r_framerate1 = { 60, 2 };
AVRational time_base_q = { 1, AV_TIME_BASE };
//Duration between 2 frames (us)
int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / av_q2d(r_framerate1));
//内部时间戳
//Parameters
enc_pkt.pts = av_rescale_q(framecnt*calc_duration, time_base_q, time_base);
enc_pkt.dts = enc_pkt.
enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base);
//转换PTS/DTS(Convert PTS/DTS)
enc_pkt.pos = -1;
framecnt++;
ofmt_ctx-&duration = enc_pkt.duration *
/* mux encoded frame */
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
if (ret & 0)
int flush_encoder_a(){
AVPacket enc_pkt_a;
if (!(ofmt_ctx-&streams[audio_st-&index]-&codec-&codec-&capabilities &
CODEC_CAP_DELAY))
enc_pkt_a.data = NULL;
enc_pkt_a.size = 0;
av_init_packet(&enc_pkt_a);
ret = avcodec_encode_audio2(ofmt_ctx-&streams[audio_st-&index]-&codec,&enc_pkt_a,NULL,&got_frame);
av_frame_free(NULL);
if(ret&0){
if(!got_frame){
LOGE("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n", enc_pkt_a.size);
av_bitstream_filter_filter(faacbsfc, ofmt_ctx-&streams[audio_st-&index]-&codec, NULL, &enc_pkt_a.data, &enc_pkt_a.size, enc_pkt_a.data, enc_pkt_a.size, 0);
//Write PTS
AVRational time_base=ofmt_ctx-&streams[audio_st-&index]-&time_
//表示一秒30帧
AVRational r_framerate1 = {pCodecCtx_a-&sample_rate, 1 };
AVRational time_base_q = AV_TIME_BASE_Q;
//Duration between 2 frames (us)两帧之间的时间间隔,这里的单位是微秒
int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / av_q2d(r_framerate1));
//内部时间戳
//Parameters
int64_t timett = av_gettime();
int64_t now_time = timett - start_
enc_pkt_a.pts = av_rescale_q(now_time, time_base_q, time_base);;
enc_pkt_a.dts=enc_pkt_a.
enc_pkt_a.duration = av_rescale_q(calc_duration, time_base_q, time_base);
enc_pkt_a.pts = av_rescale_q(nb_samples*calc_duration, time_base_q, time_base);
enc_pkt_a.dts=enc_pkt_a.
enc_pkt_a.duration = av_rescale_q(calc_duration, time_base_q, time_base);*/
enc_pkt_a.pos = -1;
framecnt_a++;
ofmt_ctx-&duration = enc_pkt_a.duration * framecnt_a;
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt_a);
if (ret & 0)
com_example_sqqfinalrecord_FfmpegHelper
* Signature: ()I
JNIEXPORT jint JNICALL Java_com_example_sqqfinalrecord_FfmpegHelper_flush
(JNIEnv *env, jclass cls){
flush_encoder();
flush_encoder_a();
//Write file trailer
av_write_trailer(ofmt_ctx);
com_example_sqqfinalrecord_FfmpegHelper
* Signature: ()I
JNIEXPORT jint JNICALL Java_com_example_sqqfinalrecord_FfmpegHelper_close
(JNIEnv *env, jclass cls){
if (video_st)
avcodec_close(video_st-&codec);
if (audio_st)
avcodec_close(audio_st-&codec);
avio_close(ofmt_ctx-&pb);
avformat_free_context(ofmt_ctx);
android的代码就不贴了,可以去我的github上看,地址:
推流的话ffmpeg上面的代码中也有了,不再过多介绍。
具体的就去看源码就行。
android客户端可优化之处
上面采集音频部分使用的AudioRecord,可以做进一步优化,直接在jni中就可以采集音频数据,就不用jni和java代码传数据了,使用的是OpenSl ES,大家可以搜一下,这个我还在做。。。可参考这里直接做:
流媒体服务器的搭建
这个没什么好讲的,直接下载,地址:,具体其他的细节,还是比较简单的
推流端的写法
我做的时候参考的一些文章(除了雷神的,这个太有名了大家都知道),分享给大家
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:48427次
排名:千里之外
原创:47篇
转载:13篇
评论:21条
(1)(5)(4)(5)(5)(24)(14)(1)(1)安卓手机怎么才能快手上直播游戏 知道解答一下
经营类:1、游戏发展国2、吃货大食堂3、冒险迷宫村4、和风物语5、口袋商业街6、二战风云7、蘑菇园8、模拟人生系列角色扮演类:1、艾亚迪诺32、艾亚迪诺43、泽...
火拼泡泡龙,俄罗斯方块,割绳子,小鳄鱼爱洗澡,植物大战僵尸,暴力摩托,一笔画,会说话的汤姆猫,水果忍者,宠物连连看,黄金矿工······在网上搜手机小游戏,安卓...
经营类:1、游戏发展国2、吃货大食堂3、冒险迷宫村4、和风物语5、口袋商业街6、二战风云7、蘑菇园8、模拟人生系列角色扮演类:1、艾亚迪诺32、艾亚迪诺43、泽...
火拼泡泡龙,俄罗斯方块,割绳子,小鳄鱼爱洗澡,植物大战僵尸,暴力摩托,一笔画,会说话的汤姆猫,水果忍者,宠物连连看,黄金矿工······在网上搜手机小游戏,安卓...
答: #HOTEL
SUNROUTE TAIPEI(台北灿路都饭店)#可以订单人间,到时候再加钱升级成双人间吗?
答: 美国苹果公司的新款手机,全触屏的智能机,在中国卖的很贵。
答: 手机购买还是找正规卖家
天猫等网站
答: 可能被设置了禁言你IP接入吧
大家还关注
确定举报此问题
举报原因(必选):
广告或垃圾信息
激进时政或意识形态话题
不雅词句或人身攻击
侵犯他人隐私
其它违法和不良信息
报告,这不是个问题
报告原因(必选):
这不是个问题
这个问题分类似乎错了
这个不是我熟悉的地区这个人懒死了,所以做完视频就跑了
<option value='/video/av4554874/index_1.html' cid='、obs直播使用faceu直播
<option value='/video/av4554874/index_2.html' cid='、全屏游戏faceu无黑屏
视频地址复制
Flash地址复制
Html地址复制
离线看更方便
用或其他应用扫描二维码
自制 懒得剪辑随便录的随便吐槽
广播电视节目制作经营许可证:(沪)字第1248号
| 网络文化经营许可证:沪网文[6号 | 信息网络传播视听节目许可证:0910417 | 互联网ICP备案:沪ICP备号-3 沪ICP证:沪B2- | 违法不良信息举报邮箱: | 违法不良信息举报电话:转396U手游网—最好玩的手机游戏网站!
当前位置:
> 斗鱼直播伴侣安卓机直播怎么用 斗鱼直播伴侣安卓直播使用教程介绍
斗鱼直播伴侣安卓机直播怎么用 斗鱼直播伴侣安卓直播使用教程介绍
斗鱼伴侣能方便用户更好的观看直播,因此受到很多人的喜欢。但是不少用户不知道安卓机怎么使用,因此就让小编给大家讲讲怎么使用吧。
评分:4.5分
类型:视频播放
版本:1.5.1大小:15.7M
评语:斗鱼视频直播app是一款非常火爆的视频直播软件。斗鱼直播伴侣app让你可以随时随地都能在手机上进行直播和拍摄,记录你的生活,或者直播表演,还能观看其他人的表演!
斗鱼直播伴侣安卓直播使用教程介绍
1.打开进入,登陆斗鱼账号(若手机不是5.0系统,先自行刷机);
2.选择截屏直播,码率建议设定机型配置和网络上传速度,通用800-1000码率,默认手机麦克风。
不过你需要一个传屏软件mobizen――适用于国内大部分热门
优点:可以通过手机玩游戏直播,任何一款游戏都适用,可通过电脑玩游戏
缺点:没游戏声音,手机配置要求高。
直播准备:
符合直播条件的电脑和网络、直播软件、mobizen手机端和客户端(下载地址:)
本站为防止低俗内容出现,用户发表的评论需经过审核,谢谢 !
查看更多 ↓
新年大礼包剩余:0%
新年大礼包剩余:0%
新年大礼包剩余:0%
新年大礼包剩余:0%
新年大礼包剩余:0%

我要回帖

更多关于 安卓手机测试培训 的文章

 

随机推荐