API высокого уровня iOS FFMPEG - PullRequest
       27

API высокого уровня iOS FFMPEG

0 голосов
/ 10 января 2019

У меня есть видео файл с субтитрами, и я хотел бы получить от него все субтитры. С терминалом это довольно легко сделать.

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);
    }
}
...