forked from LBRYCommunity/lbry-sdk
re-use ffprobe info in stream_type
avoid duplicate args handle review comment
This commit is contained in:
parent
66857e72a4
commit
71f8965393
5 changed files with 46 additions and 17 deletions
|
@ -3168,9 +3168,11 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
f"Use --allow-duplicate-name flag to override."
|
f"Use --allow-duplicate-name flag to override."
|
||||||
)
|
)
|
||||||
|
|
||||||
file_path = await self._video_file_analyzer.verify_or_repair(
|
file_path, spec = await self._video_file_analyzer.verify_or_repair(
|
||||||
validate_file, optimize_file, file_path, ignore_non_video=True
|
validate_file, optimize_file, file_path, ignore_non_video=True
|
||||||
)
|
)
|
||||||
|
kwargs.update(spec)
|
||||||
|
|
||||||
claim = Claim()
|
claim = Claim()
|
||||||
claim.stream.update(file_path=file_path, sd_hash='0' * 96, **kwargs)
|
claim.stream.update(file_path=file_path, sd_hash='0' * 96, **kwargs)
|
||||||
tx = await Transaction.claim_create(
|
tx = await Transaction.claim_create(
|
||||||
|
@ -3364,9 +3366,10 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
if fee_address:
|
if fee_address:
|
||||||
kwargs['fee_address'] = fee_address
|
kwargs['fee_address'] = fee_address
|
||||||
|
|
||||||
file_path = await self._video_file_analyzer.verify_or_repair(
|
file_path, spec = await self._video_file_analyzer.verify_or_repair(
|
||||||
validate_file, optimize_file, file_path, ignore_non_video=True
|
validate_file, optimize_file, file_path, ignore_non_video=True
|
||||||
)
|
)
|
||||||
|
kwargs.update(spec)
|
||||||
|
|
||||||
if replace:
|
if replace:
|
||||||
claim = Claim()
|
claim = Claim()
|
||||||
|
|
|
@ -341,23 +341,46 @@ class VideoFileAnalyzer:
|
||||||
|
|
||||||
return scan_data
|
return scan_data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _build_spec(scan_data):
|
||||||
|
assert scan_data
|
||||||
|
|
||||||
|
duration = float(scan_data["format"]["duration"]) # existence verified when scan_data made
|
||||||
|
width = -1
|
||||||
|
height = -1
|
||||||
|
for stream in scan_data["streams"]:
|
||||||
|
if stream["codec_type"] != "video":
|
||||||
|
continue
|
||||||
|
width = max(width, int(stream["width"]))
|
||||||
|
height = max(height, int(stream["height"]))
|
||||||
|
|
||||||
|
log.debug(" Detected duration: %f sec. with resolution: %d x %d", duration, width, height)
|
||||||
|
|
||||||
|
spec = {"duration": duration}
|
||||||
|
if height >= 0:
|
||||||
|
spec["height"] = height
|
||||||
|
if width >= 0:
|
||||||
|
spec["width"] = width
|
||||||
|
return spec
|
||||||
|
|
||||||
async def verify_or_repair(self, validate, repair, file_path, ignore_non_video=False):
|
async def verify_or_repair(self, validate, repair, file_path, ignore_non_video=False):
|
||||||
if not validate and not repair:
|
if not validate and not repair:
|
||||||
return file_path
|
return file_path, {}
|
||||||
|
|
||||||
if ignore_non_video and not file_path:
|
if ignore_non_video and not file_path:
|
||||||
return file_path
|
return file_path, {}
|
||||||
|
|
||||||
await self._verify_ffmpeg_installed()
|
await self._verify_ffmpeg_installed()
|
||||||
try:
|
try:
|
||||||
scan_data = await self._get_scan_data(validate, file_path)
|
scan_data = await self._get_scan_data(validate, file_path)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
if ignore_non_video:
|
if ignore_non_video:
|
||||||
return file_path
|
return file_path, {}
|
||||||
raise
|
raise
|
||||||
|
|
||||||
fast_start_msg = await self._verify_fast_start(scan_data, file_path)
|
fast_start_msg = await self._verify_fast_start(scan_data, file_path)
|
||||||
log.debug("Analyzing %s:", file_path)
|
log.debug("Analyzing %s:", file_path)
|
||||||
|
spec = self._build_spec(scan_data)
|
||||||
log.debug(" Detected faststart is %s", "false" if fast_start_msg else "true")
|
log.debug(" Detected faststart is %s", "false" if fast_start_msg else "true")
|
||||||
container_msg = self._verify_container(scan_data)
|
container_msg = self._verify_container(scan_data)
|
||||||
bitrate_msg = self._verify_bitrate(scan_data, file_path)
|
bitrate_msg = self._verify_bitrate(scan_data, file_path)
|
||||||
|
@ -367,7 +390,7 @@ class VideoFileAnalyzer:
|
||||||
messages = [container_msg, bitrate_msg, fast_start_msg, video_msg, audio_msg, volume_msg]
|
messages = [container_msg, bitrate_msg, fast_start_msg, video_msg, audio_msg, volume_msg]
|
||||||
|
|
||||||
if not any(messages):
|
if not any(messages):
|
||||||
return file_path
|
return file_path, spec
|
||||||
|
|
||||||
if not repair:
|
if not repair:
|
||||||
errors = ["Streamability verification failed:"]
|
errors = ["Streamability verification failed:"]
|
||||||
|
@ -418,6 +441,6 @@ class VideoFileAnalyzer:
|
||||||
raise
|
raise
|
||||||
log.info("Unable to transcode %s . Message: %s", file_path, str(e))
|
log.info("Unable to transcode %s . Message: %s", file_path, str(e))
|
||||||
# TODO: delete partial output file here if it exists?
|
# TODO: delete partial output file here if it exists?
|
||||||
return file_path
|
return file_path, spec
|
||||||
|
|
||||||
return str(output)
|
return str(output), spec
|
||||||
|
|
|
@ -253,7 +253,7 @@ class Stream(BaseClaim):
|
||||||
if stream_type in ('image', 'video', 'audio'):
|
if stream_type in ('image', 'video', 'audio'):
|
||||||
media = getattr(self, stream_type)
|
media = getattr(self, stream_type)
|
||||||
media_args = {'file_metadata': None}
|
media_args = {'file_metadata': None}
|
||||||
if file_path is not None:
|
if file_path is not None and not all((duration, width, height)):
|
||||||
try:
|
try:
|
||||||
media_args['file_metadata'] = binary_file_metadata(binary_file_parser(file_path))
|
media_args['file_metadata'] = binary_file_metadata(binary_file_parser(file_path))
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -33,7 +33,7 @@ async def process_video(analyzer, video_file):
|
||||||
transcode = input("Would you like to make a repaired clone now? [y/N] ")
|
transcode = input("Would you like to make a repaired clone now? [y/N] ")
|
||||||
if transcode == "y":
|
if transcode == "y":
|
||||||
try:
|
try:
|
||||||
new_video_file = await analyzer.verify_or_repair(True, True, video_file)
|
new_video_file, _ = await analyzer.verify_or_repair(True, True, video_file)
|
||||||
print("Successfully created ", new_video_file)
|
print("Successfully created ", new_video_file)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Unable to complete the transcode. Message: ", str(e))
|
print("Unable to complete the transcode. Message: ", str(e))
|
||||||
|
|
|
@ -52,12 +52,15 @@ class TranscodeValidation(ClaimTestCase):
|
||||||
self.assertEqual(code, 0, output)
|
self.assertEqual(code, 0, output)
|
||||||
|
|
||||||
async def test_should_work(self):
|
async def test_should_work(self):
|
||||||
new_file_name = await self.analyzer.verify_or_repair(True, False, self.video_file_name)
|
new_file_name, _ = await self.analyzer.verify_or_repair(True, False, self.video_file_name)
|
||||||
self.assertEqual(self.video_file_name, new_file_name)
|
self.assertEqual(self.video_file_name, new_file_name)
|
||||||
new_file_name = await self.analyzer.verify_or_repair(True, False, self.video_file_ogg)
|
new_file_name, _ = await self.analyzer.verify_or_repair(True, False, self.video_file_ogg)
|
||||||
self.assertEqual(self.video_file_ogg, new_file_name)
|
self.assertEqual(self.video_file_ogg, new_file_name)
|
||||||
new_file_name = await self.analyzer.verify_or_repair(True, False, self.video_file_webm)
|
new_file_name, spec = await self.analyzer.verify_or_repair(True, False, self.video_file_webm)
|
||||||
self.assertEqual(self.video_file_webm, new_file_name)
|
self.assertEqual(self.video_file_webm, new_file_name)
|
||||||
|
self.assertEqual(spec["width"], 1280)
|
||||||
|
self.assertEqual(spec["height"], 720)
|
||||||
|
self.assertEqual(spec["duration"], 15.054)
|
||||||
|
|
||||||
async def test_volume(self):
|
async def test_volume(self):
|
||||||
self.conf.volume_analysis_time = 200
|
self.conf.volume_analysis_time = 200
|
||||||
|
@ -75,7 +78,7 @@ class TranscodeValidation(ClaimTestCase):
|
||||||
with self.assertRaisesRegex(Exception, "Container format is not in the approved list"):
|
with self.assertRaisesRegex(Exception, "Container format is not in the approved list"):
|
||||||
await self.analyzer.verify_or_repair(True, False, file_name)
|
await self.analyzer.verify_or_repair(True, False, file_name)
|
||||||
|
|
||||||
fixed_file = await self.analyzer.verify_or_repair(True, True, file_name)
|
fixed_file, _ = await self.analyzer.verify_or_repair(True, True, file_name)
|
||||||
pathlib.Path(fixed_file).unlink()
|
pathlib.Path(fixed_file).unlink()
|
||||||
|
|
||||||
async def test_video_codec(self):
|
async def test_video_codec(self):
|
||||||
|
@ -91,7 +94,7 @@ class TranscodeValidation(ClaimTestCase):
|
||||||
with self.assertRaisesRegex(Exception, "faststart flag was not used"):
|
with self.assertRaisesRegex(Exception, "faststart flag was not used"):
|
||||||
await self.analyzer.verify_or_repair(True, False, file_name)
|
await self.analyzer.verify_or_repair(True, False, file_name)
|
||||||
|
|
||||||
fixed_file = await self.analyzer.verify_or_repair(True, True, file_name)
|
fixed_file, _ = await self.analyzer.verify_or_repair(True, True, file_name)
|
||||||
pathlib.Path(fixed_file).unlink()
|
pathlib.Path(fixed_file).unlink()
|
||||||
|
|
||||||
async def test_max_bit_rate(self):
|
async def test_max_bit_rate(self):
|
||||||
|
@ -111,7 +114,7 @@ class TranscodeValidation(ClaimTestCase):
|
||||||
with self.assertRaisesRegex(Exception, "pixel format does not match the approved"):
|
with self.assertRaisesRegex(Exception, "pixel format does not match the approved"):
|
||||||
await self.analyzer.verify_or_repair(True, False, file_name)
|
await self.analyzer.verify_or_repair(True, False, file_name)
|
||||||
|
|
||||||
fixed_file = await self.analyzer.verify_or_repair(True, True, file_name)
|
fixed_file, _ = await self.analyzer.verify_or_repair(True, True, file_name)
|
||||||
pathlib.Path(fixed_file).unlink()
|
pathlib.Path(fixed_file).unlink()
|
||||||
|
|
||||||
async def test_audio_codec(self):
|
async def test_audio_codec(self):
|
||||||
|
@ -125,7 +128,7 @@ class TranscodeValidation(ClaimTestCase):
|
||||||
with self.assertRaisesRegex(Exception, "Audio codec is not in the approved list"):
|
with self.assertRaisesRegex(Exception, "Audio codec is not in the approved list"):
|
||||||
await self.analyzer.verify_or_repair(True, False, file_name)
|
await self.analyzer.verify_or_repair(True, False, file_name)
|
||||||
|
|
||||||
fixed_file = await self.analyzer.verify_or_repair(True, True, file_name)
|
fixed_file, _ = await self.analyzer.verify_or_repair(True, True, file_name)
|
||||||
pathlib.Path(fixed_file).unlink()
|
pathlib.Path(fixed_file).unlink()
|
||||||
|
|
||||||
async def test_extension_choice(self):
|
async def test_extension_choice(self):
|
||||||
|
|
Loading…
Reference in a new issue