У меня есть видео файл с субтитрами, и я хотел бы получить от него все субтитры. С терминалом это довольно легко сделать.
ffmpeg -i video.mkv -map 0:s:0 subs.srt
Как я могу выполнить эту команду на iOS?
Редактировать
Или, может быть, вы знаете простой способ получить субтитры из видеофайла? Сбой av_guess_format
возвращает NULL
.
+ (void)readSubtitles:(NSString *)videoPath saveFolder:(NSString *)saveFolder {
AVFormatContext *pFormatCtx;
av_register_all();
avcodec_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, [videoPath UTF8String], NULL, NULL) != 0) {
return;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
return;
}
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
NSString *subPath = [saveFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"sub_%d.srt", i]];
[self parseSubtitles:pFormatCtx streamIdx:i savePath:subPath];
}
}
}
+ (void)parseSubtitles:(AVFormatContext *)context streamIdx:(int)idx savePath:(NSString *)savePath {
const char *filename = [savePath UTF8String];
AVStream *avstream = context->streams[idx];
AVCodec *codec = avcodec_find_decoder( avstream->codec->codec_id );
int result = avcodec_open2( avstream->codec, codec, NULL );
AVOutputFormat *outFormat = av_guess_format( NULL, "sub.mp4", NULL );
NSAssert(outFormat != NULL, @"Error finding format"); // !!! fails !!!
NSLog(@"Found output format: %@ (%@)", [NSString stringWithUTF8String:outFormat->name], [NSString stringWithUTF8String:outFormat->long_name]);
AVFormatContext *outFormatContext;
avformat_alloc_output_context2( &outFormatContext, NULL, NULL, filename );
AVCodec *encoder = avcodec_find_encoder( outFormat->subtitle_codec );
// checkResult( encoder != NULL, "Error finding encoder" );
NSLog(@"Found encoder: %@", [NSString stringWithUTF8String:encoder->name]);
AVStream *outStream = avformat_new_stream( outFormatContext, encoder );
AVCodecContext *c = outStream->codec;
result = avcodec_get_context_defaults3( c, encoder );
// outStream->codecpar
NSLog(@"outstream codec: %@", [NSString stringWithUTF8String:outStream->codec]);
NSLog(@"Opened stream %d, codec=%d", outStream->id, outStream->codec->codec_id);
result = avio_open( &outFormatContext->pb, filename, AVIO_FLAG_WRITE );
// checkResult( result == 0, "Error opening out file" );
// cerr << "out file opened correctly" << endl;
result = avformat_write_header( outFormatContext, NULL );
// checkResult(result==0, "Error writing header");
// cerr << "header wrote correctly" << endl;
result = 0;
AVPacket pkt;
av_init_packet( &pkt );
pkt.data = NULL;
pkt.size = 0;
// cerr << "srt codec id: " << AV_CODEC_ID_SUBRIP << endl;
while( av_read_frame( context, &pkt ) >= 0 )
{
if(pkt.stream_index != idx)
continue;
int gotSubtitle = 0;
AVSubtitle subtitle;
result = avcodec_decode_subtitle2( avstream->codec, &subtitle, &gotSubtitle, &pkt );
uint64_t bufferSize = 1024 * 1024 ;
uint8_t *buffer = (uint8_t *)malloc(bufferSize * sizeof(uint8_t));
memset(buffer, 0, bufferSize);
if( result >= 0 )
{
result = avcodec_encode_subtitle( outStream->codec, buffer, bufferSize, &subtitle );
// cerr << "Encode subtitle result: " << result << endl;
}
// cerr << "Encoded subtitle: " << buffer << endl;
free(buffer);
}
}