Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Windows.h>
- #include <fstream>
- #include <iostream>
- #include <array>
- #include <string>
- #include <vector>
- #include <regex>
- #include <chrono>
- #include "gumbo.h"
- #include <cpr/cpr.h>
- extern "C"
- {
- #include <libavformat/avformat.h>
- #include <libavcodec/avcodec.h>
- #include <libavutil/avutil.h>
- #include <libswscale/swscale.h>
- }
- std::string protocols{ "file,http,https,tls,tcp" };
- class av_packet_pointer
- {
- public:
- AVPacket * m_p;
- av_packet_pointer()
- {
- m_p = av_packet_alloc();
- }
- ~av_packet_pointer()
- {
- av_packet_free(&m_p);
- }
- operator AVPacket * () { return m_p; }
- AVPacket * operator ->() { return m_p; }
- };
- int main(int argc, char * argv[])
- {
- // Set the URL of the live stream website
- std::string url = "https://www.twitch.tv/ca2software";
- auto r = cpr::Get(cpr::Url{ url });
- //// Check the status code to ensure the request was successful
- //if (r.status_code == 200) {
- // // Parse the website data using Gumbo
- // GumboOutput* output = gumbo_parse(r.text.c_str());
- // // Find all of the <a> elements in the document
- // std::vector<GumboNode*> anchors;
- // GumboVector* anchor_vector = &output->root->v.element.children;
- // for (unsigned int i = 0; i < anchor_vector->length; ++i) {
- // GumboNode* node = static_cast<GumboNode*>(anchor_vector->data[i]);
- // if (node->type == GUMBO_NODE_ELEMENT &&
- // node->v.element.tag == GUMBO_TAG_A) {
- // anchors.push_back(node);
- // }
- // }
- // Find the <a> element with the M3U8 manifest file URL
- std::string manifest_url{ "https://video-weaver.lhr08.hls.ttvnw.net/v1/playlist/CqgFUF8AHWpIPV_PDqy-Nzef7Kfax0IWeQyjfzMZr7moMc7uYmyAUxO4xbUcUWg1zjx-8sWpqCwHGm84aeoU2Gz8u-0AqDYvs8G8JbR2lFUjH0FK_XRl17E2MAy3vjurpR-fMPSjzsorM2yj0D0UPSEwCUPYlYsv-bpbbbnBmrUAgwz5HbHpR-MsTL_NiG-nxiQ1EQmaDdezmKGtAJlkJsf170ImzyvI8MOMl1tWfj0Mx-GIp8B6uarF4JcCpWQxGPWGUiU0w3P9WK-FkvzfdutL0ETHsdpZlxe46FL3YKCSwhykIapLCQEGG9JBZeyVTEY74ETd7m6qtP71wvln0E5l7Po4Awrsb5owkGcbK41H5D-MxrbX9zoBLQfywH0Jj8zEWAfPnICrgmyKEdFMHoSoLVbgtFyPv_KQjMVPq2rBMqtLYINKucN_CsSAQraNaZqTHoBa64p_JwCxmREL8Trlvc9EOpRcBMhITkS3en9056bPOgCwU0JaWdkkv89JVMFdMjH2wfEWu5wurJ9WpKrgRH1nbfhMwlueM8sg6BpQdJ4lnqa9kC9YD2pCp40oVzKoiiY6gcW3jTP1y8ayWCkLXZr-rnUlP5xT9SYXbYt7Tn89ea_5WbL9Rm2VJiPo63NjwW91xz3BNNEpqaF-4rDkqQ6KR2K4MmZ8MVVcXjwWd5uk0QisLiyihzf1DjQr4dvvsNpSZ0e64wwRw7tXPtSJO5iDrknRRMvmWFO5IMD9OMRjviqaw25H0VFFnxwh8kZ82dimrgXYxyR2VYuOaBr2HAak9-iXheNjJWV1v14TEk4DZ7QlJ4-2GsAAnz7kRPCKc6MVJiCXM2Z_kiFxBvGck4S1_7LUewFs9Ojjf_3xMBnSwcGsQiTFJkwg63EgZvHf7WNsa6UTXVsaDOaCWtwiXNlqkV-_jyABKgl1cy1lYXN0LTEwgAQ.m3u8" };
- /*for (const auto& anchor : anchors) {
- GumboAttribute* href = gumbo_get_attribute(&anchor->v.element.attributes, "href");
- if (href && strlen(href->value) > 4 && std::string(href->value).compare(strlen(href->value) - 4, 4, ".m3u8") == 0)
- {
- manifest_url = href->value;
- break;
- }
- }*/
- // Download the manifest file if a URL was found
- if (!manifest_url.empty()) {
- r = cpr::Get(cpr::Url{ manifest_url });
- // Check the status code to ensure the request was successful
- if (r.status_code == 200)
- {
- // Save the manifest file data to a string
- std::string manifest = r.text;
- // Extract the URLs of the media files from the manifest file data
- std::regex media_url_regex(R"(https://[^\s,"]+.ts)");
- std::sregex_iterator it(manifest.begin(), manifest.end(), media_url_regex);
- std::sregex_iterator end;
- std::vector<std::string> media_urls;
- while (it != end) {
- media_urls.push_back(it->str());
- ++it;
- }
- // Initialize the FFmpeg libraries
- avformat_network_init();
- // Open the output MP4 file for writing
- AVFormatContext * output_format_context = NULL;
- avformat_alloc_output_context2(&output_format_context, NULL, NULL, "output.mp4");
- AVStream * output_video_stream = avformat_new_stream(output_format_context, NULL);
- const AVCodec * output_video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
- AVCodecContext * output_video_codec_context = avcodec_alloc_context3(output_video_codec);
- output_video_codec_context->width = 1280;
- output_video_codec_context->height = 720;
- avcodec_parameters_from_context(output_video_stream->codecpar, output_video_codec_context);
- av_dump_format(output_format_context, 0, "R:\\LiveStream\\output.mp4", 1);
- if (avio_open(&output_format_context->pb, "R:\\LiveStream\\output.mp4", AVIO_FLAG_WRITE) < 0) {
- std::cerr << "Failed to open output file" << std::endl;
- return 1;
- }
- avformat_write_header(output_format_context, NULL);
- int fileIterator{ 0 };
- // Loop through the media file URLs and download and write each one
- for (const auto & media_url : media_urls) {
- // Download the media file
- r = cpr::Get(cpr::Url{ media_url });
- // Check the status code to ensure the request was successful
- if (r.status_code != 200) {
- std::cerr << "Failed to download media file" << std::endl;
- return 1;
- }
- // Save the media file data to a string
- std::string media_data = r.text;
- // Save the media file data to a temporary file
- //std::string filename = std::to_string(++fileIterator) + ".ts";
- std::ofstream tmp_file("tmp.ts", std::ios::binary);
- tmp_file.write(media_data.c_str(), media_data.length());
- tmp_file.close();
- // Open the temporary TS file for reading
- AVFormatContext * input_format_context = avformat_alloc_context();
- input_format_context->protocol_whitelist = protocols.data();
- avformat_open_input(&input_format_context, "tmp.ts", NULL, NULL);
- avformat_find_stream_info(input_format_context, NULL);
- // Find the first video stream in the file
- int video_stream_index = -1;
- for (unsigned int i = 0; i < input_format_context->nb_streams; i++) {
- if (input_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
- video_stream_index = i;
- break;
- }
- }
- if (video_stream_index == -1) {
- std::cerr << "Failed to find video stream in media file" << std::endl;
- return 1;
- }
- // Open the video codec for the stream
- const AVCodec * input_video_codec = avcodec_find_decoder(input_format_context->streams[video_stream_index]->codecpar->codec_id);
- AVCodecContext * input_video_codec_context = avcodec_alloc_context3(input_video_codec);
- avcodec_parameters_to_context(input_video_codec_context, input_format_context->streams[video_stream_index]->codecpar);
- avcodec_open2(input_video_codec_context, input_video_codec, NULL);
- // Allocate memory for the decoded video frame
- AVFrame * input_video_frame = av_frame_alloc();
- if (!input_video_frame)
- {
- std::cerr << "Failed to allocate input frame\n";
- return 1;
- }
- AVFrame * output_video_frame = av_frame_alloc();
- if (!output_video_frame)
- {
- std::cerr << "Failed to allocate output frame\n";
- return -1;
- }
- // Encode and write the frame
- av_packet_pointer packet{};
- //if (!packet) {
- // // Handle packet allocation failure
- // std::cerr << "Failed to allocate packet!\n";
- //}
- //else
- //{
- //
- //}
- // Define the scaling context
- struct SwsContext * sws_context = nullptr;
- // Decode and write the video frames
- while (true)
- {
- auto res = av_read_frame(input_format_context, packet);
- if (res < 0)
- {
- break;
- }
- if (packet->size <= 0)
- {
- break;
- }
- if (packet->stream_index == video_stream_index)
- {
- // Send the packet to the decoder
- int result = avcodec_send_packet(input_video_codec_context, packet);
- if (result < 0) {
- std::cerr << "Failed to send packet to decoder" << std::endl;
- return 1;
- }
- packet->size -= result;
- packet->data += result;
- // Receive a decoded frame from the decoder
- result = avcodec_receive_frame(input_video_codec_context, input_video_frame);
- if (result == AVERROR(EAGAIN) || result == AVERROR_EOF) {
- // No frame was produced, continue decoding
- continue;
- }
- else if (result < 0) {
- std::cerr << "Failed to receive frame from decoder" << std::endl;
- return 1;
- }
- if (sws_context == nullptr)
- {
- sws_context = sws_getContext(input_video_codec_context->width, input_video_codec_context->height, input_video_codec_context->pix_fmt,
- output_video_codec_context->width, output_video_codec_context->height, output_video_codec_context->pix_fmt,
- SWS_BICUBIC, NULL, NULL, NULL);
- }
- // Write the decoded frame to the output file if one was received
- if (result >= 0)
- {
- // Convert the frame to the desired format if necessary
- sws_scale(sws_context, input_video_frame->data, input_video_frame->linesize, 0, input_video_codec_context->height, output_video_frame->data, output_video_frame->linesize);
- // Set the frame's pts value
- output_video_frame->pts = av_rescale_q(input_video_frame->pts, input_format_context->streams[video_stream_index]->time_base, output_video_stream->time_base);
- // Encode and write the frame
- av_packet_pointer output_packet{};
- if (!output_packet) {
- // Handle packet allocation failure
- std::cerr << "Failed to allocate output_packet!\n";
- }
- int result = avcodec_send_frame(output_video_codec_context, output_video_frame);
- if (result < 0) {
- std::cerr << "Failed to send frame for encoding" << std::endl;
- return 1;
- }
- result = avcodec_receive_packet(output_video_codec_context, output_packet);
- if (result == 0) {
- // Set the packet's pts and dts values
- output_packet->pts = av_rescale_q(output_packet->pts, output_video_codec_context->time_base, output_video_stream->time_base);
- output_packet->dts = av_rescale_q(output_packet->dts, output_video_codec_context->time_base, output_video_stream->time_base);
- output_packet->duration = av_rescale_q(output_packet->duration, output_video_codec_context->time_base, output_video_stream->time_base);
- output_packet->stream_index = output_video_stream->index;
- av_interleaved_write_frame(output_format_context, output_packet);
- }
- }
- }
- }
- // Clean up
- av_frame_free(&input_video_frame);
- av_frame_free(&output_video_frame);
- avcodec_free_context(&input_video_codec_context);
- avcodec_free_context(&output_video_codec_context);
- avformat_close_input(&input_format_context);
- avformat_free_context(output_format_context);
- sws_freeContext(sws_context);
- }
- // Write the trailer and close the output file
- av_write_trailer(output_format_context);
- avio_close(output_format_context->pb);
- avformat_free_context(output_format_context);
- }
- else {
- std::cerr << "Failed to download manifest file" << std::endl;
- return 1;
- }
- }
- else {
- std::cerr << "Failed to download website data" << std::endl;
- return 1;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement