HarmonyOS鸿蒙Next中ijkplayer播放MP4正常但播放m3u8提示“inputBufferInfoQueue_ is empty”
HarmonyOS鸿蒙Next中ijkplayer播放MP4正常但播放m3u8提示“inputBufferInfoQueue_ is empty”
// 无限制收流
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"infbuf","1");
// 设置无缓冲,这是播放器的缓冲区,有数据就播放
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"packet-buffering","0");
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'start-on-prepared', '1')
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'framedrop', '5')
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, 'fetch_first', 'on');
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "connect_timeout", "10000000");
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "listen_timeout", "10000000");
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "addrinfo_timeout", "10000000");
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", "10000000");
// 预读数据的缓冲区大小
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'max-buffer-size', '1024000');
// player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"fflags","nobuffer");
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", "1000000");
// 设置探测媒体文件格式时读取的字节数
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", '10240');
// 减少缓冲区大小,极小化延迟
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'min-frames', '2');
// 缓冲区最大时长(单位:微秒)
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'max_cached_duration', '1000');
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", '1');
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", '1');
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", '1');
使用ijkplayer文档里的配置可以播放,但是mp4会黑屏很久,有优化空间吗
更多关于HarmonyOS鸿蒙Next中ijkplayer播放MP4正常但播放m3u8提示“inputBufferInfoQueue_ is empty”的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者您好,
m3u8 是切片流,probesize(探测大小)太小可能导致播放器在解析索引文件或第一个 TS 切片时,还没读到完整的视频头信息:
mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", '102400');
如果某些 m3u8 流依然报错,可以尝试关闭硬解测试:
mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", '0');
测试部分mp4链接,暂无黑屏很久的现象,能否提供相关的测试地址
本地测试代码如下:
import {
IjkMediaPlayer,
LogUtils,
OnVideoSizeChangedListener
} from '@ohos/ijkplayer';
import { PromptAction } from '@kit.ArkUI';
export enum PlayStatus {
INIT = 0,
PAUSE = 1,
PLAY = 2,
};
@Entry
@Component
struct PageDemo {
private videoUrl: string = '';
uiContext: UIContext = this.getUIContext();
promptAction: PromptAction = this.uiContext.getPromptAction();
@State mContext: object | undefined = undefined;
private mIjkMediaPlayer = IjkMediaPlayer.getInstance();
private controlPlayStatus = PlayStatus.INIT;
private videoWidth: string = '100%';
private initAspectRatio: number = 1;
@State videoAspectRatio: number = this.initAspectRatio;
@State isRecord: boolean = false;
private recordSaveFilePath: string = '';
aboutToDisappear() {
this.mIjkMediaPlayer.setScreenOnWhilePlaying(false);
if (this.controlPlayStatus !== PlayStatus.INIT) {
this.stop();
}
}
/**
* 延时播放
* @param context
*/
private initDelayPlay(context: object) {
this.mContext = context;
setTimeout(() => {
this.startResumePlay();
}, 300);
}
private startResumePlay() {
LogUtils.getInstance().LOGI('startResumePlay start this.controlPlayStatus:' + this.controlPlayStatus);
if (this.controlPlayStatus === PlayStatus.INIT) {
this.play(this.videoUrl.toString());
}
if (this.controlPlayStatus === PlayStatus.PAUSE) {
this.mIjkMediaPlayer.start();
}
}
private play(url: string) {
this.initPlayer(url);
this.mIjkMediaPlayer.prepareAsync();
this.mIjkMediaPlayer.start();
}
private initPlayer(url: string) {
// 设置XComponent回调的context
if (!!this.mContext) {
this.mIjkMediaPlayer.setContext(this.mContext, 'xcomponentId');
}
if (this.controlPlayStatus === PlayStatus.INIT) {
this.mIjkMediaPlayer.reset();
}
this.controlPlayStatus = PlayStatus.PLAY;
// 设置debug模式
this.mIjkMediaPlayer.setDebug(true);
// 初始化配置
this.mIjkMediaPlayer.native_setup();
// 初始化配置后需要重新设置音频流音量,否则音量为默认值1.0
// 设置视频源
this.mIjkMediaPlayer.setDataSource(url);
// // 设置视频源http请求头
// let headers = new Map([
// ['user_agent', 'Mozilla/5.0 BiliDroid/7.30.0 (xxxx.com)'],
// ['referer', 'xxx.xxx.xxxx.com']
// ]);
// this.mIjkMediaPlayer.setDataSourceHeader(headers);
// 无限制收流
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"infbuf","0");
// 设置无缓冲,这是播放器的缓冲区,有数据就播放
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"packet-buffering","0");
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'start-on-prepared', '1')
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'framedrop', '5')
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, 'fetch_first', 'on');
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "connect_timeout", "10000000");
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "listen_timeout", "10000000");
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "addrinfo_timeout", "10000000");
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", "10000000");
// 预读数据的缓冲区大小
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'max-buffer-size', '1024000');
// player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"fflags","nobuffer");
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", "1000000");
// 设置探测媒体文件格式时读取的字节数
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", '102400');
// 减少缓冲区大小,极小化延迟
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'min-frames', '2');
// 缓冲区最大时长(单位:微秒)
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, 'max_cached_duration', '1000');
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", '1');
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", '1');
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", '1');
this.registerListener();
}
// 注册ijkplayer事件监听
private registerListener() {
let mOnVideoSizeChangedListener: OnVideoSizeChangedListener = {
onVideoSizeChanged: (width: number, height: number, sarNum: number, sarDen: number) => {
if (height === 0) {
return;
}
const va = width / height;
const vpa = this.initAspectRatio;
if (vpa > va) {
this.videoWidth = (width / (height * vpa)) * 100 + '%';
} else {
this.videoWidth = '100%';
}
if (width && height) {
this.videoAspectRatio = width / height;
}
LogUtils.getInstance()
.LOGI('setOnVideoSizeChangedListener-->go:' + width + ',' + height + ',' + sarNum + ',' + sarDen);
}
};
this.mIjkMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
this.mIjkMediaPlayer.setMessageListener();
}
private stop() {
this.controlPlayStatus = PlayStatus.INIT;
this.mIjkMediaPlayer.stop();
this.mIjkMediaPlayer.release();
}
startRecord(context: UIContext, block?: (success: boolean) => void) {
let isRecord = this.mIjkMediaPlayer.isRecord();
LogUtils.getInstance().LOGI(`testTag startRecord isRecord: ${isRecord}`);
if (isRecord) {
if (block) {
block(false);
}
return;
}
this.recordSaveFilePath = context.getHostContext()?.cacheDir + '/record.mp4';
this.mIjkMediaPlayer.setRecordDefaultFrameRate('30', false);
let result = this.mIjkMediaPlayer.startRecord(this.recordSaveFilePath);
LogUtils.getInstance().LOGI(`testTag startRecord recordSaveFilePath : ${this.recordSaveFilePath} result : ${result}`);
this.promptAction.openToast({
message: '开始录制'
});
if (block) {
block(result ? true : false);
}
}
stopRecord(context: UIContext, block?: (success: boolean, filePath: string) => void) {
let isRecord = this.mIjkMediaPlayer.isRecord();
LogUtils.getInstance().LOGI(`testTag stopRecord isRecord: ${isRecord}`);
if (!isRecord) {
if (block) {
block(false, '');
}
return;
}
this.mIjkMediaPlayer.stopRecord().then((result) => {
if (!result) {
LogUtils.getInstance().LOGI(`stopRecord fail: ${result}`);
this.promptAction.openToast({
message: '录制失败'
});
return;
} else {
this.promptAction.openToast({
message: '录制完成'
});
}
});
}
screenshot() {
let saveFilePath = this.getUIContext().getHostContext()?.cacheDir + '/screen.jpg';
this.mIjkMediaPlayer.screenshot(saveFilePath).then((result) => {
if (!result) {
this.promptAction.openToast({
message: '截屏失败'
});
} else {
this.promptAction.openToast({
message: '截屏成功'
});
}
});
}
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Auto, justifyContent: FlexAlign.Start }) {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text('ijkplayer播放器')
.fontSize('30px')
.fontColor(Color.White)
.margin('10px')
.fontWeight(FontWeight.Bold);
}
.height('100px')
.width('100%')
.backgroundColor(Color.Black);
Divider().vertical(false).strokeWidth('20px').color(Color.White).lineCap(LineCapStyle.Round);
Stack({ alignContent: Alignment.Center }) {
Column() {
XComponent({
id: 'xcomponentId',
type: 'surface',
libraryname: 'ijkplayer_napi'
})
.onLoad((event?: object) => {
if (!!event) {
this.initDelayPlay(event);
}
})
.onDestroy(() => {
})
.width('100%')
.aspectRatio(this.videoAspectRatio)
}
.aspectRatio(this.videoAspectRatio);
}
.width('100%')
.backgroundColor('#000000')
.clip(true);
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Button(this.isRecord ? '结束录屏' : '开始录屏')
.onClick(() => {
if (this.isRecord) {
// 结束录屏
this.stopRecord(this.getUIContext());
} else {
// 开始录屏
this.startRecord(this.getUIContext());
}
this.isRecord = !this.isRecord;
})
.width('400px')
.height('80px')
.margin('15px');
Button('截图')
.onClick(() => {
this.screenshot();
})
.width('400px')
.height('80px')
.margin('15px');
};
}
}
}
更多关于HarmonyOS鸿蒙Next中ijkplayer播放MP4正常但播放m3u8提示“inputBufferInfoQueue_ is empty”的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
+1 帮顶一下
在HarmonyOS鸿蒙Next中,ijkplayer播放m3u8时出现“inputBufferInfoQueue_ is empty”错误,通常与网络流媒体协议处理有关。该错误表明播放器的输入缓冲区队列为空,可能由于m3u8索引文件解析失败、网络请求超时或媒体片段(TS文件)未能正确加载导致。建议检查网络连接稳定性、m3u8文件格式合规性及服务器响应状态。
在HarmonyOS Next中使用ijkplayer播放m3u8时出现“inputBufferInfoQueue_ is empty”错误,通常与媒体解码器的缓冲区管理有关。这个问题在播放HLS流媒体时较为常见,而本地MP4文件播放正常,说明问题可能出在网络流处理和缓冲区配置上。
从你提供的配置来看,你已经设置了多个优化参数,但有几个关键点需要注意:
-
缓冲区配置冲突:你同时设置了
infbuf(无限缓冲)和packet-buffering=0(无缓冲),这可能导致内部缓冲区状态不一致。对于m3u8流媒体,建议优先使用infbuf,但需要确保网络流能够持续提供数据。 -
缓冲区大小限制过严:
max_cached_duration设置为1000微秒(仅1毫秒),这对于网络流来说可能太短,容易导致缓冲区饥饿。建议适当增加这个值,例如设置为3000000(3秒)。 -
解码器配置:你已启用mediacodec,但m3u8流可能包含的编码格式或分片特性与硬解码器兼容性有关。可以尝试临时关闭mediacodec测试是否是解码器问题:
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", "0"); -
针对HLS的特定配置:添加以下HLS专用参数可能有助于解决问题:
player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", "0"); player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "fastseek"); -
网络缓冲区调整:增加网络缓冲区大小:
player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", "5242880"); // 增加到5MB
关于MP4播放黑屏问题,通常与start-on-prepared参数和缓冲区配置有关。可以尝试:
- 将
start-on-prepared设置为0,通过prepareAsync()回调后再开始播放 - 适当增加
max_cached_duration到2000000(2秒)以上 - 确保MP4文件的编码格式与设备硬解码兼容
建议先简化配置,逐步添加优化参数,以定位具体是哪个参数组合导致了问题。

