AiPE

3.5. 스택 오버플로우 질문 : Not able to merge init.mp4 and seg-*.m4s with ffmpeg and python due to its file format difference 번역 본문

[XiBBaL] Development Project/Laftel Downloader

3.5. 스택 오버플로우 질문 : Not able to merge init.mp4 and seg-*.m4s with ffmpeg and python due to its file format difference 번역

Oshimaker XiBBaL 2023. 2. 4. 02:17
반응형

내가 올린 질문인데, 답변(comment형식으로)이 달려서 어느 정도 결론이 난 것 같아 번역해보도록 하겠다.

 

 

원문은 스택오버플로우 질문이고, 영어이다. 답변 또한 영어이다.

https://stackoverflow.com/questions/75266232/not-able-to-merge-init-mp4-and-seg-m4s-with-ffmpeg-and-python-due-to-its-file

 

Not able to merge init.mp4 and seg-*.m4s with ffmpeg and python due to its file format difference

I'm developing video downloader (only for free videos) for korean anime streaming site https://laftel.net/ I guess laftel.net uses mpeg-dash for their streaming. I found "init.mp4" file a...

stackoverflow.com

 

 


1. 질문 본문

Not able to merge init.mp4 and seg-*.m4s with ffmpeg and python due to its file format difference

파일 포맷 차이로 인해 init.mp4파일과 .m4s 세그먼트 파일을 ffmpeg와 python을 이용해 병합할 수 없음

 

 

 

I'm developing video downloader (only for free videos) for korean anime streaming site https://laftel.net/

나는 무료공개된 비디오들에 한해 한국 애니메이션 공유 사이트 laftel.net의 비디오 다운로더를 개발하는 중이다.

 

I guess laftel.net uses mpeg-dash for their streaming. I found "init.mp4" file and "segments-number.m4s" files in chrome developer tools.

내 생각에는 laftel.nt이 영상 스트리밍을 위해 mpeg-dash 방식을 이용하는 듯하다. 나는 크롬 개발자도구에서 init.mp4 파일과 segment.m4s파일을 발견했다. 

 

Code below downloads seg-1.m4s (name of the first segment) to seg-239.m4s (name of the last segment) file and init.mp4 file and it works.

아래에 있는 코드는 seg-1.m4s (첫번째 세그먼트의 이름) 부터 seg-239.m4s (마지막 세그먼트의 이름) 까지, 그리고 init.mp4파일을 다운로드한다. 그리고 아래 코드는 정상 작동한다.

 

(Skip the beginning becasue there is a code that collects "Request-URL" for each .m4s files in network stream)
(코드의 앞부분은 네트워크 스트림에서 각각의 .m4s에 대해 Reqeust URL을 수집하는 부분이기 때문에 생략)

#variable "found" is part of the "Request-URL"
#"found"변수는 "Request URL"의 일부분

def curl_m4s():
    for i in range(1,240): #number of the .m4s segment file is constant at 239 (.m4s세그먼트의 개수는 239개로 일정)
        vid_url = f"https://mediacloud.laftel.net/{found}/video/avc1/2/seg-{i}.m4s"
        aud_url = f"https://mediacloud.laftel.net/{found}/audio/mp4a/eng/seg-{i}.m4s"
        
        if i < 10: #for single digit num (한자리수)
            os.system(f"curl {vid_url} > {location}/vids/vid00{i}.m4s")
            os.system(f"curl {aud_url} > {location}/auds/aud00{i}.m4s")
            sleep(random.randint(1,3))
            
        elif i < 100: #for double digit num (두자리수)
            os.system(f"curl {vid_url} > {location}/vids/vid0{i}.m4s")
            os.system(f"curl {aud_url} > {location}/auds/aud0{i}.m4s")
            sleep(random.randint(1,3))
            
        else: #for three digit num (세자리수)
            os.system(f"curl {vid_url} > {location}/vids/vid{i}.m4s")
            os.system(f"curl {aud_url} > {location}/auds/aud{i}.m4s")
            sleep(random.randint(1,3))

location = os.getcwd()

os.system(f"curl https://mediacloud.laftel.net/{found}/video/avc1/2/init.mp4 > {location}/vids/vid_init.mp4")
os.system(f"curl https://mediacloud.laftel.net/{found}/audio/mp4a/eng/init.mp4 > {location}/auds/aud_init.mp4")
os.system(f"curl https://mediacloud.laftel.net/{found}/stream.mpd > {location}/stream.mpd")

curl_m4s()
#use curl in cmd and downloads each of the .m4s (001 ~ 239)
#001~239의 .m4s를 다운하기 위해 cmd명령어 중 curl을 사용함

 

So in the vids folder i have "init.mp4" for video and "seg-1.m4s ~ seg-239.m4s" for video and in the auds folder i have "init.mp4" for audio and "seg-1.m4s ~ seg-239.m4s" for audio

위 코드대로 하면 vids폴더 안에는 비디오용 init.mp4와 비디오용 seg-1.m4s 부터 seg-239.m4s가 존재하게 된다. 또, auds폴더 안에는 오디오용 init.mp4와 오디오용 seg-1.m4s 부터 seg-239.m4s까지가 존재하게 된다.

 

Problem is, I cannot merge init file and segment files. I have no idea about combining .mp4 and .m4s together. There are a lot of example codes for merging init.m4s + seg-.m4s but I couldn't find init.mp4 + seg-.mp4 codes.

문제는, 이 세그먼트 파일들을 하나로 병합할 수가 없다는 것이다. .mp4랑 .m4s를 어떻게 하나로 합쳐야 하는지 모르겠다. init.m4s와 segment.m4s를 병합하는 코드는 예제가 많이 있는데, init.mp4와 segment.m4s를 병합하는 방법은 예제 코드를 찾기가 어려웠다.

 

I tried to merge segments together first, like this and it works.
나는 일단 세그먼트 파일들을 먼저 병합해보려고 했고, 아래와 같이 작동은 했다.

 

location = os.getcwd()

os.system(f"cd {location}")
os.system("copy /b vid*.m4s vid_full.m4s")

 

and now, i want to merge init.mp4 becasue it has very much information about whole video files. But how??

그리고, init.mp4파일을 여기에 병합하고 싶은데 (init.mp4파일이 전체 비디오에 대한 모든 정보를 포함하므로), 어떻게 해야 하는가??

 

I tried these and none of them worked (looks like Successfull merge but it do not contain any watchable video)

나는 아래 방법"들"을 시도해봤고 그 중 단 하나도 정상작동하지 않았다. (병합이 완료된 것으로 보여도 막상 영상을 열어보면 가용성 있는 비디오 파일이 아니었다.)

 

# vid_full is merged segment files (seg-1.m4s + ... + seg-239.m4s)
 
1. 
os.system("copy /b init.mp4 + vid*.m4s video_full.m4s")
os.system("ffmpeg -i video_full.m4s -c:a copy video_full.mp4")


2. 
os.system("type vid_init.mp4 index.txt > Filename.mp4")


3. 
import os 

os.system("ffmpeg -i vid_full.m4s -c:a copy vid_full.mp4")
os.system("copy /b vid_init.mp4 + vid_full.mp4 VIDEO.mp4")

 

All problem occurs the format of the init file is .mp4. If it was .m4s I guess I could merge it.

모든 문제는 init파일의 포맷이 .mp4여서 발생한 것 같은데, 만약 init파일이 .m4s였다면 병합할 수 있었을 것 같다.

(나중에 답변에 의해서 밝혀졌지만 내가 한 병합 방법은 애초부터 옳은 방법이었고, 내 예상과 달리 문제는 다른 곳에 있었으며 만약 init파일이 .m4s였어도 똑같은 문제가 발생했을 것이다.)

 

and I guess i must merge init file and segments files together both in .m4s format. Is it right? Via ffmpeg, i couldn't encode init.mp4 to init.m4s so this is the problme also.

그리고 내 생각엔 init파일이랑 세그먼트 파일을 모두 .m4s포맷으로 일단 병합해놔야 할 것 같은데, 이게 맞나? ffmpeg로는 init.mp4를 init.m4s로 바꿀 수가 없으니까 말이다. 이거도 문제다.

(ffmpeg는 m4s를 mp4로 바꾸는 기능은 지원하는데 mp4를 m4s로 바꾸는 기능은 지원하지 않는 듯 하다. 하려고 하면 버그가 난다.)

 

So, Please help me merge init.mp4 and segments.m4s

따라서, init.mp4와 segments.m4s를 병합하는 데에 도움을 요청한다.

All methods are wellcome at least it is based on python.

파이썬을 기반으로 하는 방법이라면 어떤 방법이든 좋다.

 

  1. I tried to merge init.mp4 + merged_segment.m4s but it failed
  2. init.mp4 + 병합된_segment.m4s 를 시도했지만 실패
  3. I tried to convert init.mp4 to init.m4s via ffmpeg but it failed
  4. init.mp4 를 init.m4s로 변환해보려고 시도했지만 실패 
  5. I tried to convert all the segments to .mp4 files and merge into init.mp4 but it failed
  6. 모든 세그먼트를 각각 .mp4로 변환한 후 init.mp4와 병합하려고 시도했으나 실패

I want to merge init file and segment files and make playable video. Pleas Teach me how to do this.

나는 init파일과 세그먼트들을 잘 합쳐가지고 재생가능한 비디오를 만들고 싶다. 어떻게 하는지 가르쳐주면 좋겠다.

 

 

Links below are what I used for my test :

아래는 내가 코드 테스트를 위해 사용한 링크들이다.

(댓글에서 답변자분이 직접 테스트해보겠다고, 추가해달라고 하셔서 추가함)

 

[Laftel.net URL] https://laftel.net/player/40269/46123

[Request URL for init.mp4 (video)] https://mediacloud.laftel.net/2021/04/46773/v15/video/dash/video/avc1/2/init.mp4

[Request URL for init.mp4 (audio)] https://mediacloud.laftel.net/2021/04/46773/v15/video/dash/audio/mp4a/eng/init.mp4

[Request URL for seg-1.m4s (video)] https://mediacloud.laftel.net/2021/04/46773/v15/video/dash/video/avc1/2/seg-1.m4s

[Request URL for seg-1.m4s (audio)] https://mediacloud.laftel.net/2021/04/46773/v15/video/dash/audio/mp4a/eng/seg-1.m4s

 

 

 

 


2. 답변

VC.One이라는 분께서 아래와 같이 답변해주시고 감사하게도 파일 테스트까지 진행해주셨다.

이 또한 번역해보겠다.

 

 

 

(1) MP4, M4V, M4A, M4S, 3GP are all variations of the same file format (eg: M4A is just a signal that it's an MP4 without a video track inside those bytes). (2) It should be enough to take init.mp4 as the starting bytes and then at its ending, just join the bytes of seg-1.m4s followed by seg-2.m4s etc etc... (3) Make sure you are downloading bytes as binary data and not as maybe, UTF text string etc. (4) Finally provide a download link to your testable "init.mp4" and "seg-1.m4s" files for advice about why your input is not giving a working file.

– VC.One / Jan 31 at 12:22

(1) MP4, M4V, M4A, M4S, 3GP는 같은 파일 포맷의 여러 변형들입니다. (예를 들어서, M4A는 해당 파일 바이트 안에 오디오 트랙이 없는 MP4파일이라는 의미일 뿐입니다.)

(2) init.mp4를 시작 바이트로 두고 연이어서 seg-1.m4s seg-2.m4s ... 등등을 결합하면 충분할 것입니다.

(3) 너가 파일을 UTF텍스트 문자열 등이 아닌 이진 데이터로 다운로드 하고 있는지 확인해보세요.

(4) 마지막으로, 너가 쓴 질문을 테스트해보기 위한 "init.mp4"와 "seg-1.m4s" 파일에 대한 링크를 제공해주세요. 그러면 당신의 작업이 왜 정상작동하는 파일이 되지 못했는지에 대한 조언을 받을 수 있을 것입니다.

 

 

 

 

First of all, thank you so much for your responding my question! Your comment was very helpful. I added the URL and Request-URL for the test (same what I used for my test) in the end of the question. You adviced me "It should be enough to take init.mp4 as the starting bytes and then at its ending, just join the bytes of seg-1.m4s followed by seg-2.m4s etc etc... " I understood what you mean roughly.. But what method should I take specifically? 

1) copy /b .\vid\init.mp4+.\vid\*.m4s vid_full.m4s and ffmpeg -i vid_full.m4s -c:a copy video.mp4 (2) copy /b .\vid\init.mp4+.\video\*.m4s vid_full.mp4 and ffmpeg -i vid_full.mp4 -c:a copy video.mp4 (3) ffmpeg -f concat -safe 0 -i vid_index.txt -c copy vid_full.mp4 and ffmpeg -i vid_full.mp4 -c:a copy video.mp4 *vid_index.txt is a list that contains init.mp4 and segments file name 1 to 239. Is there any available method out of this? or could you teach me another right way? Much appreciate for your reading and commenting my questions. Thanks!

– XiBBaL / 2 days ago

먼저, 제 질문에 답변해주셔서 감사합니다! 당신의 답변이 많은 도움이 되었습니다. 제가 테스트에 사용했던 것과 동일한 URL과 Request-URL을 질문의 맨 끝 부분에 추가해 두었습니다.

 

제게 "init.mp4와 세그먼트 파일들을 순서대로 결합하면 충분할 것이다" 라고 조언해 주셨는데, 대략적으로 무슨 말인지는 이해 했습니다. 하지만 제가 구체적으로 어떤 수단을 취해야 하는지에 대해서는 아직 잘 모르겠습니다.

 

(1) copy /b .\vid\init.mp4+.\vid\*.m4s vid_full.m4s and ffmpeg -i vid_full.m4s -c:a copy video.mp4 

(2) copy /b .\vid\init.mp4+.\video\*.m4s vid_full.mp4 and ffmpeg -i vid_full.mp4 -c:a copy video.mp4 

(3) ffmpeg -f concat -safe 0 -i vid_index.txt -c copy vid_full.mp4 and ffmpeg -i vid_full.mp4 -c:a copy video.mp4 

*vid_index.txt파일은 init.mp4와 segment.m4s파일을 순서대로 써 놓은 파일입니다.

 

위 방법 중 가능한 방법이 있나요? 아니면 다른 올바른 방법을 가르쳐 주실 수 있나요? 제 질문을 읽어주시고 답변을 달아 주셔서 감사합니다.

 

 

 

 

I checked your files. Video's Seg-1.mp4 is encrypted (with Shaka packager) and that's why joining init and seg-1 parts together does not make a playable file. 

– VC.One / yesterday

당신의 파일을 확인해보았습니다. 비디오의 첫 번째 세그먼트 파일 (m4s를 mp4로 잘못 쓰신 듯. 아니면 맨 처음 댓글의 논리에 따라 아예 같은 확장자로 취급하여 쓰신 듯) 은 Shaka packager로 "암호화" 되어 있습니다. 그리고 이 암호화는 왜 당신이 init파일과 segment파일을 결합해도 재생가능한 비디오를 만들지 못했는지에 대한 이유입니다. 

 

 

 

 

Thanks a lot. I'm not really sure I can decrypt it but I will try it. Again, thanks a lot. 

– XiBBaL / yesterday

감사합니다. 제가 그 암호화를 다시 복호화할 수 있을지에 대해서는 자신이 없지만 시도해보겠습니다. 다시한번 감사드립니다.

반응형